5 ms·
My take would be: Your 3a is certainly necessary in order for each individual monad to be useful, but it is not general (i.e it depends on the monad how you do
by btschaegg 4y ago
My take would be:
Your 3a is certainly necessary in order for each individual monad to be useful, but it is not general (i.e it depends on the monad how you do it). Therefore, it's not part of the criteria of what it means to be a monad.
Examples:
- Async: Block and wait for your Async<T> to finish or fail. (Note that Async<T> can still be useful without that if you can simply register a final continuation callback with side effects)
- Option: Check if there is a value and unwrap it if that's the case. Or, maybe more idiomatic: Some way to write a `match` statement ("if there's a value, do A. Otherwise do B. Both have to return the same result type")
- List: Provide ways to check the length and access each individual value in the list.
- Stream: Provide a way to wait for the next value.
…and so on and so forth.
Your 3b is implementable in terms of `bind` and `return` (and, in case your monad is also a functor, even in terms of `map`).
Edit: To drive the point about 3a home a bit more:
The reason why monads (and functors) as a pattern are interesting is that they provide the formalistic means to write "imperative" code by writing pure functional "in between" code:
Do A
…and then do B
…and then do C
Different monads essentially only influence what "and then" means. A lot of languages have syntactic sugar for this kind of "and then" lists, for example:
Haskell: do notation
F#: Computation expressions (e.g. `async` or `seq` blocks)
Python, C#, Javascript: Async methods and functions
C#: Inline SQL with LINQ
Rust: `try` and `async` blocks
You'll note that each of these notations return the final monad instance without unwrapping it. That's because "unwrapping" is either not general enough for the notation or not always desirable. I.e. an `async` method in C# returns a `Task<T>`, you'll have to block for the result yourself.
So, the "Monad" pattern is only concerned with how you can compose operations, not with how you can get to the resulting value.
- substation13 4y agoExcept many of those syntactic-sugars do not operate on well-formed monads. JavaScript collapses a Promise<Promise<t>> to a Promise<t>, for example.