One thing that this article and lot of other Monad articles gloss over is the scoping in "do" notation and when using the >>= operator.
The example:
return 7 >>= (\x -> Writer (x+1,"inc."))
>>= (\x -> Writer (2*x,"double."))
>>= (\x -> Writer (x-1,"dec."))
works for this example, but a more accurate representation of how "do" notation is expanded is:
return 7 >>= (\x -> Writer (x+1,"inc.")
>>= (\x -> Writer (2*x,"double.")
>>= (\x -> Writer (x-1,"dec."))))
Note that I've moved the parentheses.
Actually, you can, equivalently, omit the parentheses for the same meaning, because the '->' has very low precedence:
return 7 >>= \x -> Writer (x+1,"inc.")
>>= \x -> Writer (2*x,"double.")
>>= \x -> Writer (x-1,"dec.")
The point is, most times each of subsequent functions need to "see" what was in scope in the earlier functions. Most times, the later monadic actions need information that is pulled out of the monad in previous actions.
For example, consider the following:
main = putStrLn "Enter your first name" >>=
\_ -> getLine >>=
\first -> putStrLn "Enter your last name" >>=
\_ -> getLine >>=
\last -> putStrLn ("Hello " ++ first ++ " " ++ last ++ ".")
The last monadic action needs both "first" and "last" to both be in scope. This only works because of the way that it is implicitly parenthesized.
Until I "got" this, I was very confused by most of the Monad examples I found.
Here's an article I wrote about the IO monad which also makes this point: https://github.com/Patient0/IOMonad
The example:
works for this example, but a more accurate representation of how "do" notation is expanded is: Note that I've moved the parentheses.Actually, you can, equivalently, omit the parentheses for the same meaning, because the '->' has very low precedence:
The point is, most times each of subsequent functions need to "see" what was in scope in the earlier functions. Most times, the later monadic actions need information that is pulled out of the monad in previous actions.For example, consider the following:
The last monadic action needs both "first" and "last" to both be in scope. This only works because of the way that it is implicitly parenthesized.Until I "got" this, I was very confused by most of the Monad examples I found.
Here's an article I wrote about the IO monad which also makes this point: https://github.com/Patient0/IOMonad