Hacker News new | ask | show | jobs
by canndrew2016 2895 days ago
> Monads as implemented in pure functional programming languages like Haskell cannot usefully abstract over asynchronous and synchronous IO in Rust for a variety of reasons having to do with the way the type system exposes low level details by virtue of Rust being a systems programming language. I do not believe that `do` notation could be a useful mechanism for achieving either the ergonomics or the performance that async/await syntax will have in Rust.

Sorry, but I don't buy it. I had a half-baked, unfinished proposal for an effects system that would have allowed Rust to implement async/await just as efficiently (no stackful coroutines) along with any number of other effects [0]. Maybe it wouldn't have been a good idea due to stretching Rust's complexity budget too far, but that's very different from saying it's impossible. Having watched the development of Rust closely I really think that the design team just didn't understand the theory side well enough to be able explore the design space here. (I'm not being as critical as I might sound, PL theory is hard and the Rust devs have wielded it much more competently than the designers of any other non-research language).

[0] https://internals.rust-lang.org/t/start-of-an-effects-system...

4 comments

A Rust-flavored effect system is quite a bit different from do-notation. You're probably right that such a thing could achieve the same ergonomics and efficiency as built-in async/await, but you're also probably right that it would be a huge amount of complexity.

When people say that monads and do-notation don't work in Rust, they're talking about a user-level Monad trait and a simple CPS transform built on top of it:

- Such a monad trait is impossible to write even with HKT because it would have to abstract over both Option/Result (type constructors) and Iterator/Future (traits)

- Such a CPS transform would be extremely limited (not composable with built-in loop structures) and/or extremely tricky around TCE, lifetimes, and allocation (the typical type for `>>=` would involve `Fn` trait objects...).

Effects bypass this by leaving the CPS transform in the compiler, instead only exposing delimited continuations to userspace. Which is basically what async/await does, just non-generically.

The first part of your comment is unresponsive to mine; the last part is pretty rude & factually wrong (we are not motivated to implement an effect system right now; we understand the theory).

Sticking to the first part: an effect system is not what the user I was responded to was talking about. They were talking about building do notation on top of type classes with higher kinded polymorphism, which cannot effectively abstract over the monadic operations in Rust.

> The first part of your comment is unresponsive to mine;

I interpreted OP's comment as complaining about the lack of more general abstractions in Rust that would allow you to implement async/await. Your comment specifically mentioned Haskell-style monads (eg. a `Monad` trait), but that's not the only way to implement something like this.

> the last part is offensive & wrong

Quoting steveklabnik:

> it’s an open research problem if do notation can work in Rust. Until that’s solved at all, we’re just not sure it’s possible. ... "Open question" doesn't mean "impossible", mind you. But nobody has ever come up with a design. In the meantime, we have users to support...

Isn't this what I was saying? "We don't know how to do it, so we're going with the easier option."

Edit: To be clear, I don't think async/await we've ended up with is necessarily in the wrong direction. But I also don't think that "we thoroughly explored the design space of do/monads/effects and concluded that they were impossible to implement ergonomically/efficiently" is really true.

"impossible" is a highly contextual term here. Adding this to Rust isn't "impossible", of course it isn't. We can "just" slowly turn Rust into Haskell using the edition mechanism. Done.

When folks say something is "impossible" in such a context, they mean "given the constraints", which include goals the lang team has for the language. An effects system is pretty heavyweight and may violate these goals.

I think that there is not a definition of the Monad trait - not just undesirable, not possible - that can abstract over all Futures and Iterators as implemented in Rust. You would have to use some kind of trait object & lose the incredible inlining benefits that Rust gets from how these interfaces are designed today.

This is separate from effect systems, which I never said was not possible. rpjohnst's parallel response sums up the key differences between monads and an effect system.

I'm scratching my head at the premise of this comment. The grandparent is positing that monads/do-notation would not be useful in Rust; this one appears to be trying to accuse it of saying that an effect system in Rust is impossible? Nowhere does withoutboats say anything about an effect system, or that anything is impossible. Did you reply to the wrong comment?
> Having watched the development of Rust closely I really think that the design team just didn't understand the theory side well enough to be able explore the design space here.

You might want to do a Google Scholar search on Niko Matsakis and Aaron Turon before making silly claims like this.