Abstract return types on its own wouldn’t completely replace this, or not as nicely, at least not without additional nontrivial extensions. You would have to write something like:
fn compose<A, B, C, F: Fn(A) -> B, G: Fn(B) -> C>(f: F, g: G) -> abstract Fn(A) -> C { move |a| g(f(a)) }
fn compose_mut<A, B, C, F: FnMut(A) -> B, G: FnMut(B) -> C>(f: F, g: G) -> abstract FnMut(A) -> C { move |a| g(f(a)) }
fn compose_once<A, B, C, F: FnOnce(A) -> B, G: FnOnce(B) -> C>(f: F, g: G) -> abstract FnOnce(A) -> C { move |a| g(f(a)) }
The issue is that there’s no way to say things like “the output abstract type is FnMut
iff the input types are”. Off the top of my head, I don’t think the more-general formulation of named module-level abstract type
s would provide for this either. (And, for what it’s worth, my sense is that any extension enabling this would likely be too complex to be worthwhile, considering that you can just use struct
s with explicit impl
s for this instead.)
So I think that struct Compose
is in fact the right way to do this, and will be for some time. Inclusion in std
might be reasonable from my perspective.