Suppose I have a higher order function, such as composition from this answer:
fn compose<A, B, C, G, F>(f: F, g: G) -> impl Fn(A) -> C
where
F: Fn(A) -> B,
G: Fn(B) -> C,
{
move |x| g(f(x))
}
and I want to partially apply it, as in
fn id<T>(x: &T) -> &T { x }
fn compose_with_id<T, U, F>(f: F) -> impl Fn(&T) -> U
where
F: Fn(&T) -> U
{
compose(id, f)
}
This doesn't compile. IIUC the issue is that at the compose callsite, we must substitute a specific type for A (including a specific lifetime), but the return value needs to implement Fn(&'a T) -> U for all 'a. I tried moving the call to compose into a closure:
fn compose_with_id<T, U, F>(f: F) -> impl Fn(&T) -> U
where
F: Fn(&T) -> U
{
move |t| compose(id, f)(t)
}
This also doesn't compile. The problem is now that compose is trying to take ownership of f each time the resulting function is called. I don't see a way to fix compose_with_id (without insisting F: Copy); compose takes ownership of f, which can only happen once, so we must choose one lifetime, but the return value needs to handle any lifetime.
We could create a variant of compose that works for references:
fn compose<A, B, C, G, F>(f: F, g: G) -> impl Fn(&A) -> C
where
F: Fn(&A) -> &B,
G: Fn(&B) -> C,
{
move |x| g(f(x))
}
(whose return value has a HRTB) but it can't be used for non-reference inputs.
How can I define compose such that it can be partially applied to non-copyable functions with or without reference inputs?