Monads in haskell are notoriously hard to understand, just google it and see how many different tutorials that have been devoted to it. Some tutorials start with the IO monad becuse it is supposed to be the easiest one to start with. I found it more easy to start with the Maybe monad and that is what I am going to do here.
The Maybe monad is defined as follows:
data Maybe a = Nothing | Just a
How does this differ from the Bool definition?
data Bool = False | True
In the Bool definition we say that the type Bool can have two values, True or False. Instances of Bool include Eq and five others instances. That's it. With this we can use it in toy functions like
cmp :: Int -> Bool cmp x | x < 0 = False | otherwise = True
This is all fine, we can check if a value is negative. Lets add another toy function:
evn :: Int -> Bool evn x | mod x 2 == 0 = True | otherwise = False
Now we can check for even numbers and negative numbers. What happens if we want to chain these funcitons? Like first check if a value is negative and only then check if the value is even. Or more generally, we want to compute something and then do another computation if some condition is true. We could solve this by combining these two function into one and check the conditions in the function. But when we add more conditions our function will grow and get more complicated with more if then else branches. The underlying problem is that cmp returns Bool but evn requires an Int as input. And it is here the Maybe monad can be used. As can be seen in the definition, Maybe takes another type a in the contructor. This could be a String, Float or as in our case, an Int. If we rewrite our two toy functions with the Maybe monad it will look like this:
cmpM :: Int -> Maybe Int cmpM x | x < 0 = Nothing | otherwise = Just x evnM :: Int -> Maybe Int evnM x | mod x 2 == 0 = Just x | otherwise = Nothing
Now we can chain these two functions
>>> cmpM 23 >>= evnM >>> Nothing >>> cmpM 20 >>= evnM >>> Just 20 >>> cmpM (-20) >>= evnM >>> Nothing
There is a lot to say about this, but for now let's just look at the definition of the bind (>>=) function
(>>=) :: m a -> (a -> m b) -> m b
It takes a monad m and a type a and then takes only the a type and return monad m with another value b. Like cmpM returns a Maybe Int that is going in to a lambda function that returns Int to cmpM. The lambda function really "lifts" the Int from Maybe and gives it to the next function. Is this clear? Probably not, but it is a start at least. Here is an in depth article about state monads. And here is a nice tutorial. This one is elegant but somewhat hard to understand. Finaly, there is a tutorial that uses pictures to illustrate monads that I found particularily nice.