|
My problem with understanding monads was as follows: I had no problem with understanding the mathematical definition, it was easy to check that a given monad verifies the axioms. No, my problem was this one: everyone was saying "hey, you know if you have a purely functional language, it would be impossible to have IO, since e.g. a read function would have different outputs every time. We solve that with monads." But that didn't feel like an explanation. I couldn't draw a line from the monad axioms to dissolving that impossibility. It was like saying "Einstein says we can't do FTL, but we can solve that with monads". |
Take something like getStrLn (which reads a line from STDIN). What is "getStrLn", as a mathematical object? It's not a string, rather, it's some kind of "I/O operation" that when executed, returns a string. Haskell calls such an object an "IO String". Similarly, the expression (putStrLn "foo") is an I/O operation that when executed, doesn't return anything. Haskell calls this an "IO ()".
Once you develop an intuition of I/O operations, you can see how you might want to combine atomic I/O operations into larger and larger I/O operation, feeding the output from one as input into the other. Or how you could treat a plain Int as an "empty" I/O operation that when executed, simply returns the Int. And how your entire program, its "main" entry point, can be modeled simply as one large I/O operation.
You can do all of that, and write every possible kind of I/O code in Haskell, without ever learning about monads.
What are monads for, then? They generalize the structure of this approach, with its (>>=) and return operators, and apply it to other cases that don't have anything to do with I/O. But this step is completely optional! This is very similar to how the idea of a mathematical "field" generalizes the arithmetic operators (+, -, *, /) and applies them to objects that don't look anything like the rational numbers. You don't have to learn about fields to successfully use rational numbers. And we would never dream of explaining the abstract idea of fields to people before we introduce them to rational numbers. Yet almost every I/O tutorial in Haskell begins with a half-baked explanation of monads.