I often forget what a monad is, and need to keep reminding myself "remember list.map and Option.and_then? if so, then you don't need to know what a monad is". But will try thinking about burritos next time to see if it helps.
I still don't get what they have to do with i/o in Haskell, but am ok with i/o in Haskell being one of my life's forever unknowable mysteries.
I'd argue that if you know what Option.and_then does, you do know what a monad is. and_then, known as flat_map or bind in the generic case, is the quintessential operation of a monad.
One of my biggest gripes with Rust (and other languages) is lack of a good monad abstraction (and accompanying syntactic sugar). But I also acknowledge that this is a "I have done too much category theory" problem and and_then is probably a more reasonable name to those not familiar with this particular area of maths.
> I still don't get what they have to do with i/o in Haskell, but am ok with i/o in Haskell being one of my life's forever unknowable mysteries.
They don't. Not really, anyway. IO happens to be a monad, but that's not really relevant to it being used as an abstraction around side effects. Haskell being a pure language is at odds with the necessity of some side-effects, such as printing to the console. The solution is to construct a "to-do list of actions" or "blueprint" for desired side-effects. This is an instance of IO. Any such blueprint that is assigned to the name "main" is executed. That's it.
The monad part comes in when you want to construct this blueprint. It so happens that one reasonable way to do this is via flat_map.
> One of my biggest gripes with Rust (and other languages) is lack of a good monad abstraction (and accompanying syntactic sugar). But I also acknowledge that this is a "I have done too much category theory" problem and and_then is probably a more reasonable name to those not familiar with this particular area of maths.
I'm happy that Rust has iterators and I don't have to think about what a monad is at all.
The way I think about it is that the general monadic structure is that the results of an operation can cause new operations to happen with equivalent complexity. This is exactly what "flat map" is.
So what the "IO monad" in Haskell represents is the general principle across programming languages where you can, say, read a file, then for each line in the file read another file or otherwise do additional I/O -- and this can spiral out in an unbounded fashion.
As developers we can observe the monadic structure of operations everywhere (and generally seek to avoid it! Monads are fundamentally too powerful!) But whether it is worth encoding the general idea of monadic structures into the type system is a separate question. Haskell says yes, most others say no. There are good reasons both ways. (One underappreciated reason is that exposing a hierarchy of typeclasses/traits introduces API stability considerations. When Applicative was inserted in between Functor and Monad in Haskell, the whole ecosystem had to be updated.)
(Tries to fight the urge to explain, fails) it’s a construct to sequence async interactions, one after the other, without blocking. It’s very similar to c# or python’s await
I still don't get what they have to do with i/o in Haskell, but am ok with i/o in Haskell being one of my life's forever unknowable mysteries.