Twitter | Pretraživanje | |
Saoirse Shipwreckt
MONADS AND RUST A THREAD - or - why async/await instead of do notation
Reply Retweet Označi sa "sviđa mi se" More
Saoirse Shipwreckt 9. kol 2018.
Odgovor korisniku/ci @withoutboats
Let's start with borrowing across yield points. We've solved this problem for real yield points with pin, I have no idea how to solve it using a function interface like >>=
Reply Retweet Označi sa "sviđa mi se"
Saoirse Shipwreckt 9. kol 2018.
Odgovor korisniku/ci @withoutboats
So that means borrows across statements in do notation are just out of the picture. That's extremely limiting.
Reply Retweet Označi sa "sviđa mi se"
Saoirse Shipwreckt 9. kol 2018.
Odgovor korisniku/ci @withoutboats
Rust's imperative control flow statements like `return` and `break` inside of do notation also doesn't make sense, because we do not have TCP preserving closures.
Reply Retweet Označi sa "sviđa mi se"
Saoirse Shipwreckt 9. kol 2018.
Odgovor korisniku/ci @withoutboats
So we only know how to have do notation without early return or borrowing. People say this is an open research question, but IMO its just not possible within our runtime constraints.
Reply Retweet Označi sa "sviđa mi se"
Saoirse Shipwreckt 9. kol 2018.
Odgovor korisniku/ci @withoutboats
Getting beyond that, this is assuming that "future" implements "monad," so if we could just add HKT to have a Monad trait, everything would be hunkydory. That's not true!
Reply Retweet Označi sa "sviđa mi se"
Saoirse Shipwreckt 9. kol 2018.
Odgovor korisniku/ci @withoutboats
the signature of >>= is `m a -> (a -> m b) -> m b` the signature of Future::and_then is roughly `m a -> (a -> m b) -> AndThen (m a) b`
Reply Retweet Označi sa "sviđa mi se"
Saoirse Shipwreckt 9. kol 2018.
Odgovor korisniku/ci @withoutboats
That is, in order to reify the state machine of their control flow for optimization, both Future and Iterator return a new type from their >>= op, not "Self<U>"
Reply Retweet Označi sa "sviđa mi se"
Saoirse Shipwreckt 9. kol 2018.
Odgovor korisniku/ci @withoutboats
Also, our functions are not a `->` type constructor; they come in 3 different flavors, and many of our monads use different ones (FnOnce vs FnMut vs Fn).
Reply Retweet Označi sa "sviđa mi se"
Saoirse Shipwreckt 9. kol 2018.
Odgovor korisniku/ci @withoutboats
Okay, so Monad can't abstract over Future, but still let's have Monad. Problem: we don't have higher kinded polymorphism, and probably never will.
Reply Retweet Označi sa "sviđa mi se"
Saoirse Shipwreckt 9. kol 2018.
Odgovor korisniku/ci @withoutboats
The problem is that without currying at the type level, higher kinded polymorphism makes type inference trivially undecidable. We have no currying.
Reply Retweet Označi sa "sviđa mi se"
Saoirse Shipwreckt 9. kol 2018.
Odgovor korisniku/ci @withoutboats
In order to add higher kinded polymorphism, we'd have to restrict the sorts of types you could use in a way that would feel very arbitrary to users.
Reply Retweet Označi sa "sviđa mi se"
Saoirse Shipwreckt 9. kol 2018.
Odgovor korisniku/ci @withoutboats
In contrast, generic associated types don't have this problem, and directly solve the expressiveness problems we do have, like Iterable (abstracting over everything with a `.iter(&self)` method)
Reply Retweet Označi sa "sviđa mi se"
Saoirse Shipwreckt 9. kol 2018.
Odgovor korisniku/ci @withoutboats
(Don't get me wrong, you can write something to abstract over some monads like Option and Result using generic associated types. But its much less ergonomic than Monad in Haskell, even for those).
Reply Retweet Označi sa "sviđa mi se"
Saoirse Shipwreckt 9. kol 2018.
Odgovor korisniku/ci @withoutboats
IN CONCLUSION: a design that works in a pure FP which lazily evaluates and boxes everything by default doesn't necessarily work in an eager imperative language with no runtime.
Reply Retweet Označi sa "sviđa mi se"
Saoirse Shipwreckt 9. kol 2018.
Odgovor korisniku/ci @withoutboats
This comes up a lot, please link this thread liberally.
Reply Retweet Označi sa "sviđa mi se"