Earlier quoted context omitted.
For better or worse, "container" is the most intuitive concept to use when trying to explain monads. Yes, there are monad instances that don't really fit the container model, but they're not important at first. Definining "monad" as a thing for which monad laws hold is exactly the sort of almost-tautological non-explanation that makes people roll their eyes at FP aficionados. However, I agree that the important step…
I guess flatMap is very misleading to newcommers. Probably simply calling it chaining, composition, or even "then" would help.
Async and Await in Rust: a full proposal
171–180 of 196 posts
Re: Async and Await in Rust: a full proposal
#172This thread is so confusing to me. Not because of complex differences in a language theory, but on choices that developers do follow due to experience in ‘the past’, regarding light threads. I understand that rust has no stdlib, that go has, and that js just doesn’t have switchable stacks. But why does almost everyone inclined to async-await in general? The answers I got in other threads (not on this exact question,…
Does async/await alleviate the need for a runtime component? Because then I could see the decision make sense, else I am also really puzzled why anyone would not, given the opportunity, go with green threads (other than complex implementation, maybe).
https://github.com/nox/rust-rfcs/blob/master/text/0230-remov...
Re: Async and Await in Rust: a full proposal
#173Linux is especially problematic, asynchronous IO has arrived late, years later than IOCP and kqueue. It took multiple kernel versions to make it usable, and still the APIs are questionable, e.g. files and sockets use different ones.
Even MS failed to do it right, see a bug I found: https://github.com/dotnet/corefx/issues/25066
Re: Async and Await in Rust: a full proposal
#174Earlier quoted context omitted.
I would remove "containers" from the first line. In my reading it is ANYTHING for which monad laws hold.
For better or worse, "container" is the most intuitive concept to use when trying to explain monads. Yes, there are monad instances that don't really fit the container model, but they're not important at first. Definining "monad" as a thing for which monad laws hold is exactly the sort of almost-tautological non-explanation that makes people roll their eyes at FP aficionados. However, I agree that the important step…
Thank-you for crystallizing and articulating a frustration I have often, as a beginner to intermediate Haskeller.
Re: Async and Await in Rust: a full proposal
#175Earlier quoted context omitted.
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 effective…
> 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 resea…
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.
Re: Async and Await in Rust: a full proposal
#176Earlier quoted context omitted.
For better or worse, "container" is the most intuitive concept to use when trying to explain monads. Yes, there are monad instances that don't really fit the container model, but they're not important at first. Definining "monad" as a thing for which monad laws hold is exactly the sort of almost-tautological non-explanation that makes people roll their eyes at FP aficionados. However, I agree that the important step…
I guess flatMap is very misleading to newcommers. Probably simply calling it chaining, composition, or even "then" would help.
I feel like, now that I have a certain level of intuitive understanding of what bind does, to me, the `>>=` symbol best represents what the operation does. It just looks like some kind of physical gadget that extracts a thing from a container, does something to it, and injects it into the next container. This is pretty ironic given Haskell's (somewhat deserved) reputation as impenetrable symbol soup. I don't know whether I'd endorse trying to use an intuitive mnemonic like this to explain monads to FP beginners.
Re: Async and Await in Rust: a full proposal
#177And yet we somehow don't acknowledge the fact that this is just do-notation for some specific monad--yeah, that powerful abstraction that can't be expressed in Rust because we don't allow higher-order polymorphism. Don't get me wrong, i'm bitter because i feel like Rust really is almost in the right direction for the future of language design. Yet there is a long time before we get a language with a really precise ty…
I have been doing programming, including functional programming for more than two decades, I still don't really know what a "monad" is. Each time someone explains it to me, I understand something different.
Re: Async and Await in Rust: a full proposal
#178Earlier quoted context omitted.
Can you explain "this is less overhead than immediately suspending"? AFAICT Rust's approach is as low-overhead as it gets, since the inherent separation between future creation and future execution means that future creation doesn't need to have any cost at all. I'm also not sure it makes sense to refer to Rust's behavior as "immediately suspending", since it's not suspending anything: until someone chooses to start…
My understanding is that Rust uses LLVM coroutines[1]. In order to have the behavior where the function does not start executing immediately, you would follow the example that you can find by searching for "injected suspend point, so that the coroutine starts suspended". So what this looks like is: * Function call * The coroutine creates its frame (I believe this maps to "future creation".) * Function return (the inj…
A Rust future is also "responsible for making sure that it gets resumed appropriately if it suspends." Rust's await is even cheaper than C++/LLVM's- it doesn't do anything with an event loop either; it just returns, without atomically messing with any coroutine handle (which doesn't exist).
Further, Rust futures are poll-based, not callback-based. Your bullet list looks like this:
* Function call to the main entry point (which is really more of a constructor)
* The future creates its frame as a value type (not as a heap allocation) and initializes it with the call arguments
* Function return (not a suspend, because it returns an initialized future rather than Poll::Pending- so again more of a constructor return)
* (sometime later, often immediately) Function call to `poll` (initial resume)
* `poll` executes until a suspend point (function return)
The initial call to `poll` can happen because the constructed future was put on the event loop and scheduled, as you describe, but it can also happen merely because its caller is also a future that is already running somehow.
Also, note that "the event loop" is a rather loose concept here- it's just "the thing that calls top-level `poll` functions." The language doesn't ever submit anything to it, or signal it, or anything. Each call to `poll` receives a handle to that top-level caller, and each leaf future stashes that handle somewhere that will signal it when it's ready to resume. This even works in embedded microcontroller scenarios.
And finally, your eager execution example is addressed in Rust in two ways:
* First, ownership and the borrow checker prevent dangling references like this statically. In your particular case, the caller would increment the refcount as part of cloning an `Rc`, and then move the clone into the future. (Unless, of course, the future was short-lived enough, and you decided to take advantage of that to pass in a `&'a Value.Fn` instead.)
* Second, because future construction (the first three bullet points) and future execution (the last two) are decoupled, you can write your own function that does any extra construction work in the cases that it's actually necessary. For example, using Rust's syntax for async blocks:
pub fn render_to_llvm(.., fn_val: *Value.Fn, ..) -> impl Future {
fn_val.base.ref();
async {
defer fn_val.base.deref(comp);
// ...
}
}Re: Async and Await in Rust: a full proposal
#179Earlier quoted context omitted.
I don't have time to write a whole essay, so let me just establish my credentials: - I wrote the generic associated types RFC (how Rust will implement higher kinded polymorphism). - I wrote the const generics RFC (the closest Rust will get to dependent types). - I wrote the async/await RFC, as well as the linked blog post. That is to say that I am intimately familiar with how Rust's type system can be extended to sup…
> 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…
You might want to do a Google Scholar search on Niko Matsakis and Aaron Turon before making silly claims like this.
Re: Async and Await in Rust: a full proposal
#180And yet we somehow don't acknowledge the fact that this is just do-notation for some specific monad--yeah, that powerful abstraction that can't be expressed in Rust because we don't allow higher-order polymorphism. Don't get me wrong, i'm bitter because i feel like Rust really is almost in the right direction for the future of language design. Yet there is a long time before we get a language with a really precise ty…
I don't have time to write a whole essay, so let me just establish my credentials: - I wrote the generic associated types RFC (how Rust will implement higher kinded polymorphism). - I wrote the const generics RFC (the closest Rust will get to dependent types). - I wrote the async/await RFC, as well as the linked blog post. That is to say that I am intimately familiar with how Rust's type system can be extended to sup…
...I saw this thread too late, hopefully you will still see this comment. I'm genuinely curious.