The guy writing didn’t know about generics, so…. (to be clear, I trust the rust core devs know about these things, I’m implying that they are afraid to reference them directly because they think the M word will scare people)
My takeaway is that monads are great in a purely functional syntax, but kind of awkward in Rust, so Rust should adapt the ideas behind monads to get a syntax that fits better with Rust.
Haskell has very famously not solved this problem. As in, pretty much every academic paper published on the subject in the past 15 years includes a brief paragraph explaining why Haskell’s effect monads are terrible.
Also, it would be surprising for Rust’s developers to be scared of monads when Rust already has monads as a core language feature, with special syntax support and everything.
I wouldn’t call Monads a “language feature” of Rust.
There are some types in the standard library that have Monad properties (Option, Result, Vec,…), but there is no Monad trait that would allow to be generic over them.
There have been attempts to introduce such a trait, the most well known probably being the higher crate. However, even with that crate, it’s not easy to work with Monads.
For instance, in the stable tool-chain, it’s currently (to my knowledge) not possible to express a Free Monad without using macros. If you care for the details, I’ve written a blog post about my Adventures with Free Monads and higher. With the Nightly toolchain it is possible to write a generic Free Monad, by the way, thanks to non-lifetime-binders.
Other Monads, like State, Reader and Writer, are also challenging to implement in Rust. I did get them to work, however I failed to implement Applicative for them, so, while they are mathematically Monads, they do not have higher’s Monad trait. Here a possible future improvement of non-lifetime-binders could help. Again, a blog post: Writer and State Monad in Rust, based on higher.
Oh, and last, but not least, do-notation in Rust is a bit inconvenient, because of lifetime rules and lambda captures. For instance, using non-copy types is messy. I’ve added explicit clone support to higher, but that’s a crutch, and overly verbose.
This problem is not solved by monads, but by higher kinded types in general in languages like Haskell. They give you a uniform way to be generic over effects like async (Async<A>) vs sync (Identity<A>). Both of these can be treated as (F<A>) for all A. So a generic Into would look like the following, and no special syntax or semantics would be needed. The type system (if sound) would prevent you from misusing a trait like this.
Yeah, in all of this the annoying part is the beginning of the article mentioning that they never realized they were putting effects into the language. As far as I remember in many discussions prior to even 1.0 release people were already mentioning it regularly that it’s all monads/effect systems and to be careful to not design themselves into a corner and be really careful about adding special dedicated syntax to just a few things, like the try/result thing. Me particularly am annoyed about await keywords, because I think it’s a stupid way to do it, but at this point that battle is lost and I don’t care. Obviously since early days the problems are also known that it’s not easy to just add N-ranked types and that rust is designed is a very particular way with special constraints that just simply saying to add effects is not straightforward because of all the aliasing and ownership and linearity and abstraction over those things.
I’m interested in seeing what’s going to come out from such a focus group.
Also scala is actively doing research nowadays with effects in the language, so totally worth looking at it.
They seem quite afraid of mentioning the basis for effects that Haskell, Scala et al have used for years - Monads.
So they’re going to re-invent it all 🙃
The Rust folks know their CS and PL theory. Of course they’ve considered monads.
The guy writing didn’t know about generics, so…. (to be clear, I trust the rust core devs know about these things, I’m implying that they are afraid to reference them directly because they think the M word will scare people)
This is an interesting discussion about precisely that.
My takeaway is that monads are great in a purely functional syntax, but kind of awkward in Rust, so Rust should adapt the ideas behind monads to get a syntax that fits better with Rust.
Haskell has very famously not solved this problem. As in, pretty much every academic paper published on the subject in the past 15 years includes a brief paragraph explaining why Haskell’s effect monads are terrible.
Also, it would be surprising for Rust’s developers to be scared of monads when Rust already has monads as a core language feature, with special syntax support and everything.
I wouldn’t call Monads a “language feature” of Rust.
There are some types in the standard library that have Monad properties (Option, Result, Vec,…), but there is no Monad trait that would allow to be generic over them.
There have been attempts to introduce such a trait, the most well known probably being the higher crate. However, even with that crate, it’s not easy to work with Monads.
For instance, in the stable tool-chain, it’s currently (to my knowledge) not possible to express a Free Monad without using macros. If you care for the details, I’ve written a blog post about my Adventures with Free Monads and higher. With the Nightly toolchain it is possible to write a generic Free Monad, by the way, thanks to non-lifetime-binders.
Other Monads, like State, Reader and Writer, are also challenging to implement in Rust. I did get them to work, however I failed to implement Applicative for them, so, while they are mathematically Monads, they do not have higher’s Monad trait. Here a possible future improvement of non-lifetime-binders could help. Again, a blog post: Writer and State Monad in Rust, based on higher.
Oh, and last, but not least, do-notation in Rust is a bit inconvenient, because of lifetime rules and lambda captures. For instance, using non-copy types is messy. I’ve added explicit clone support to higher, but that’s a crutch, and overly verbose.
Yes, my thoughts exactly.
This problem is not solved by monads, but by higher kinded types in general in languages like Haskell. They give you a uniform way to be generic over effects like async (
Async<A>
) vs sync (Identity<A>
). Both of these can be treated as (F<A>
) for allA
. So a genericInto
would look like the following, and no special syntax or semantics would be needed. The type system (if sound) would prevent you from misusing a trait like this.trait Into<F,T> { def into(self): F<T>; }
Yeah, in all of this the annoying part is the beginning of the article mentioning that they never realized they were putting effects into the language. As far as I remember in many discussions prior to even 1.0 release people were already mentioning it regularly that it’s all monads/effect systems and to be careful to not design themselves into a corner and be really careful about adding special dedicated syntax to just a few things, like the try/result thing. Me particularly am annoyed about await keywords, because I think it’s a stupid way to do it, but at this point that battle is lost and I don’t care. Obviously since early days the problems are also known that it’s not easy to just add N-ranked types and that rust is designed is a very particular way with special constraints that just simply saying to add effects is not straightforward because of all the aliasing and ownership and linearity and abstraction over those things.
I’m interested in seeing what’s going to come out from such a focus group.
Also scala is actively doing research nowadays with effects in the language, so totally worth looking at it.