-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make return type of the Fn
traits an associated type
#587
Conversation
Fn
traits an associated type
Maybe this should be |
@Aatch um, yes. |
... | ||
} | ||
|
||
impl<I,F> Iterator for Map<A,B>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be Map<I, F>
?
@huonw @quantheory thanks, corrected. |
This is maybe not related to this RFC, but it might have an impact on it, so I am posting it here. Currently it is impossible to do this pub struct ComposedMut<X, Y, Z, F, G> {
f: F,
g: G
}
impl<X, Y, Z, F, G> FnMut(X) -> Z for ComposedMut<X, Y, Z, F, G>
where F: FnMut(Y) -> Z,
G: FnMut(X) -> Y {
extern "rust-call" fn call_mut(&mut self, arg: (X,)) -> Z {
let (x,) = arg;
let y = (self.g)(x);
let z = (self.f)(y);
z
}
}
pub fn compose_mut<X, Y, Z, F, G>(f: F, g: G) -> ComposedMut<X, Y, Z, F, G>
where F: FnMut(Y) -> Z,
G: FnMut(X) -> Y {
ComposedMut { f: f, g: g }
} due to a conflicting impl of |
@ruud-v-a This is indeed not really related to this RFC. Rather that is due to rust-lang/rust#19032. We do plan to to address this limitation although the exact best fix is not yet clear. It might be that negative impls are the best way forward. |
Haskell has a trick to implement var-args (e.g. printf) by overloading the return value of a function, something like trait Printf {
fn method(...) -> Self;
}
impl Printf for String {
fn method(...) -> String { /* do the printing */ }
}
impl<A, T: Printf> Printf for Box<Fn(A) -> T> {
fn method(...) -> Box<Fn(A) -> T> { /* add an argument for formatting */ }
}
fn printf<T: Printf>(fmt: String) -> T { ... } which gets used like |
@huonw Those impls are fine. It would prevent something like: impl<A,R> FnMut<A> for F {
type Output = R;
...
} that is, having a closure type that can be invoked with any return at all, regardless of argument types, but I think that's pretty related. |
Having considered for a while, I think that this RFC is really the best option overall, and it also accords with my intuition a bit better (that argument types are pretty free "inputs" that one can overload on, but result types need to depend on the arguments to some extent). I suppose that this RFC prevents overloading based on lifetimes as well as normal types in the returned type, e.g. |
Seems like a win except for the minor limitation about overloading based on lifetimes and return types. Feedback is positive. Accepted. |
Definitely welcome this change. For one, I believe it would allow for a generic implementation of partial application for closures. Along with other recent changes (associated types for operators), that would really improve the ergonomics for functional programming. I can see a number of areas where I could make good use of such a change to improve my libraries. |
Now this has landed, I ran into some issues with it. A minimal example is the following: trait FnBuilder<T> {
type F: Fn<(T,)>;
fn get(&self) -> Self::F;
}
fn iterate<T, B: FnBuilder<T>>(b: B, mut t: T) -> T {
let function = b.get();
for _ in 0i32 .. 42 {
t = function(t);
}
t
} This could be expressed before, but not any more: the compiler complains that the return type of trait FnBuilder<T> {
type F: Fn(T) -> T;
fn get(&self) -> Self::F;
}
fn iterate<T, B: FnBuilder<T>>(b: B, mut t: T) -> T {
let function = b.get();
for _ in 0i32 .. 42 {
t = function(t);
}
t
} Is it still possible to express the bound that |
@ruud-v-a This compiles: #![crate_type = "lib"]
trait FnBuilder<T> {
type Fn: Fn(T) -> T;
fn get(&self) -> Self::Fn;
}
fn iterate<T, F: Fn(T) -> T, B: FnBuilder<T, Fn=F>>(b: B, mut t: T) -> T {
let function = b.get();
for _ in 0i32 .. 42 {
t = function(t);
}
t
} Not sure why you need to "duplicate" the |
Change the return type of the
Fn
traits to be an associated type.Rendered form.
cc rust-lang/rust#20871
cc rust-lang/rust#21019