> That is, even if Rust had a monad trait, that does not mean that Try and Future could both implement it. This is because, in Haskell, these things have the same signatures. In Rust, they do not have the same signature. For reference:
This is nonsense; Try and Future are not the same thing in Haskell, there are plenty of functions you can only call with one or the other.
The point of the monad abstraction is to abstract over the part that is the same, mostly the function which Rust calls and_then:
pub fn and_then(self, f: F) -> AndThen
where
F: FnOnce(Self::Item) -> B,
B: IntoFuture,
Self: Sized,
pub fn and_then(self, op: F) -> Result
where
F: FnOnce(T) -> Result,
Obviously these signatures aren't quite identical, but they're actually even more similar than I thought; AndThen is a subtype of `impl Future`, and the fact that there's no IntoResult seems like plumbing rather than anything fundamental. So if we could write an interface like:
trait Monad> {
pub fn and_then(self: M, f: F) -> impl M
where
F: FnOnce(A) -> M
}
then these both conform to that - in the first case with M=Future and A=Self::Item, in the second case with M=Result and A=T.
Yes, there are low-level things you might want to do with Future or Result that you can't do via the monad interface - just as with any other high-level interface. But having the high-level interface available makes the simple, common cases a lot easier. I don't know what these "real, practical problems are", but they're certainly not at the syntactic/interface level.