The following function boxes a closure that takes &M
as input:
pub fn accepts_m<M>(cl: impl FnMut(&M) + 'static) -> Box<dyn FnMut(&M)>
{
Box::new(cl)
}
I want to write a function that wraps a closure that takes a subset M1
of &M
as input. To the outside, the returned boxed closure must still accept &M
as input. When called, the returned boxed closure attempts to convert &M
into M1
. If it succeeds, it calls the wrapped closure, passing M1
to it.
In essence, I am trying to simulate a partial function.
This is what I have came up with:
pub fn accepts_m_partial<M, M1>(mut cl: impl FnMut(M1) + 'static) -> Box<dyn FnMut(&M)>
where for<'a> M1: TryFrom<&'a M>
{
Box::new(move |m: &M| {
if let Ok(m1) = m.try_into() {
cl(m1);
}
})
}
Let's make a (somewhat) complicate example:
#[derive(Debug)]
enum Outer {
A { a: String },
B { b: u32 },
}
#[derive(Debug)]
enum Inner<'a> {
A { a: &'a String }
}
impl<'a> TryFrom<&'a Outer> for Inner<'a> {
type Error = ();
fn try_from(value: &Outer) -> Result<Self, Self::Error> {
match value {
Outer::A { a } => Ok(Inner::A { a }),
Outer::B { .. } => Err(()),
}
}
}
fn main() {
let b1 = accepts_m_partial::<Outer, Inner>(move |m1: Inner| {
match m1 {
Inner::A { a } => {
println!("{}", a);
// mutate the environment
}
}
});
}
Notice that Inner
is a subset of Outer
. Moreover, it contains a reference to the original String, to simulate the fact that cloning data in Inner
may be prohibitively expensive.
Unfortunately, it fails to compile:
error[E0277]: the trait bound `for<'a> Inner<'_>: TryFrom<&'a Outer>` is not satisfied
--> src/main.rs:39:41
|
39 | let b1 = accepts_m_partial::<Outer, Inner>(move |m1: Inner| {
| ^^^^^ the trait `for<'a> TryFrom<&'a Outer>` is not implemented for `Inner<'_>`
|
= help: the trait `TryFrom<&'a Outer>` is implemented for `Inner<'a>`
note: required by a bound in `accepts_m_partial`
--> src/main.rs:7:23
|
6 | pub fn accepts_m_partial<M, M1>(mut cl: impl FnMut(M1) + 'static) -> Box<dyn FnMut(&M)>
| ----------------- required by a bound in this function
7 | where for<'a> M1: TryFrom<&'a M>
| ^^^^^^^^^^^^^^ required by this bound in `accepts_m_partial`
I am having some difficulties overcoming the compilation error. Do you have any suggestions? Perhaps, the trait bound I am trying to impose is the wrong approach. However, you should still get the idea.