# My attempt at explaining monads

It is an unwritten law, that everybody learning Haskell sooner or later has to write a tutorial or explanation of the topic of monads. (The fourth monad law.)1

So here is my attempt at explaining monads, I will try to give an intuition on what monads are from the practical view of a developer. I’m going to use examples in Haskell, so yes, this time I’m going to assume, some basic knowledge of Haskell – but a seasoned developer might still be able to figure out the essence of the examples without learning Haskell.

First and foremost, monads are functors. And so the metaphor of containers works for them as well, at least as a first approximation. But what makes a functor a monad?

To make this intuitive lets start with an example of a simple task: Lets say we have a list of integers, and we want to extend the list by inserting the result of the multiplication with two, after each of them. So given a list `[1,2,3]` we want to get the list `[1,2,2,4,3,6]`.

As written in my last article for each functor there is a way to map functions, so that, staying in the picture of containers, they operate on the content of the container. In Haskell the function `fmap` does this mapping. Lists are functors, so lets try to solve the task using `fmap`:

```addTimesTwo :: Int -> [Int]

-- and fmap it into our functor:
-- returns: [[1,2],[2,4],[3,6]]
```

Ooops, that’s not what we wanted to do. I could now try this or that, but – spoiler ahead – there is absolutely no way this could be done using just `fmap`. The reason is that an `fmap`-ed function by definition can only operate on the content of our containers, but our task includes the requirement to enhance the list, which would mean to change the container itself.

In terms of types: having a list `[Int]` and a function ```Int -> [Int]```, when mapping the function to the list we will get a result of the type `[[Int]]`, but we wanted a `[Int]`. Or more general: having a functor `F a` and a function `a -> F a` mapping will give us ```F (F a)```.

Of course, the task at hand can still be solved relatively easily, we just have to operate on the list (our functor) directly:

```addTimesTwoInList :: [Int] -> [Int]

-- returns: [1,2,2,4,3,6]
```

That wasn’t to hard, was it? But we lost a lot of abstraction. Let’s say we need another function, doing the same thing, but with a different math operation, for example adding 42 instead of multiplication with two? We can write this function, too:

```addPlusFortytwoInList :: [Int] -> [Int]

-- returns: [1,43,2,44,3,45]
```

That’s a lot of duplicated logic. Let’s see if we can factor out the list manipulation in a way, so that we can use our original function `addTimesTwo`:

```applyToList :: (a -> [b]) -> [a] -> [b]
applyToList _ [] = []
applyToList f (x:xs) = f x ++ applyToList f xs

-- Try it:
-- returns: [1,2,2,4,3,6]

--returns: [1,43,2,44,3,45]
```

That’s much better! So what have we done here? Well, we wrote a special function for function application to a list.

## …with specific rules for joining in function application

While the type of standard function application is: `(a -> b) -> a -> b` we created a new variation with the type `(a -> [b]) -> [a] -> [b]`, that’s quite the similarity! The difference is the asymmetry in the argument type of the function we apply and the type of argument we provide: we only give the contents of our container (the list) to the function, which returns a new container of the same functor type (list)2, then it is the task of our new function application method, to join the two containers: the one of the argument (which it kind of kept back from the called function) and the one of the result.

As we invented a way to apply functions, we can now of define function combination as well:

```after :: (b -> [c]) -> (a -> [b]) -> (a -> [c])
after g f = applyToList g . f

-- and test it:
-- returns: [1,43,2,44,2,44,4,46,3,45,6,48]
-- returns: [1,43,2,44,2,44,4,46,3,45,6,48]
```

Ok, so that’s nice, now we have function combination for functors. But we have only defined our clever new function application for lists. The concept of automatically joining containers during function application is generic, so lets implement it for another functor. The canonical second example is `Maybe`:

```applyToMaybe :: (a -> Maybe b) -> Maybe a -> Maybe b
applyToMaybe _ Nothing = Nothing
applyToMaybe f (Just x) = f x

after2 :: (b -> Maybe c) -> (a -> Maybe b) -> (a -> Maybe c)
after2 g f = applyToMaybe g . f
```
```-- and some functions, to test it:
import Data.Char (toLower)
import Data.List (elemIndex)

firstChar :: String -> Maybe Char
firstChar "" = Nothing
firstChar (c:_) = Just c

positionInAlphabet :: Char -> Maybe Int
positionInAlphabet c = (+1) <\$> elemIndex (toLower c)
"abcdefghijklmnopqrstuvwxyz"

-- put it to the test:
applyToMaybe (positionInAlphabet `after2` firstChar) (Just "")
-- returns: Nothing
applyToMaybe (positionInAlphabet `after2` firstChar) (Just "Foo")
-- returns: Just 6
applyToMaybe (positionInAlphabet `after2` firstChar) (Just ":-)")
-- returns: Nothing
```

Ok, function application and combination with automatic handling of the functor joining works in this case, too. The only ugliness left is that we are inventing a new name for the application function (and therefore for the combination function) per functor. Unfortunately we can not write one generic `apply` for all functors, as they are to diverse in their semantics (just as we can not write one common version of fmap for all functors). So, we will need a specific implementation per functor, but we can make it ad-hoc polymorphic through a type class:

```class Functor f => FancyFunctor f where
apply :: (a -> f b) -> f a -> f b
after :: (b -> f c) -> (a -> f b) -> (a -> f c)
after g f = apply g . f

instance FancyFunctor [] where
apply _ [] = []
apply f (x:xs) = f x ++ apply f xs

instance FancyFunctor Maybe where
apply _ Nothing = Nothing
apply f (Just x) = f x
```

Now we can write function combination for our different fancy functors in a unified way:

```apply (addPlusFortytwo `after` addTimesTwo) [1..3]
-- returns: [1,43,2,44,2,44,4,46,3,45,6,48]
apply (positionInAlphabet `after` firstChar) (Just "abc")
-- returns: Just 1
```

Sweet. But what has all that to do with monads? Well, we just invented them! Our special `apply` function is called bind in terms of monads in Haskell, and the `after` operator derived from it is called Kleisli composition. Functors for which these operations are defined are called monads, as is the matching type class in Haskell.

And yes, lists and `Maybe` are monads in Haskell, so the functions we just created are already predefined for them.

## Some unnecessary confusion

So what are these functions called in standard haskell monads? Well, just like the standard function application `\$` and function combination `.` they are defined as infix operators in haskell: the commonly used bind operator is `>>=` and the matching Kleisli composition is written as `>=>`. But a quick glance at the types of the monad functions shows that the arguments are flipped compared to our versions:

```(>>=) :: Monad m => m a -> (a -> m b) -> m b
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
```

So we have to write:

```import Control.Monad

(Just "Example") >>= (firstChar >=> positionInAlphabet)
-- returns: Just 5
(Just ")-:") >>= (firstChar >=> positionInAlphabet)
-- returns: Nothing
```

I think, this is a pity as it obfuscates the similarity between the function application operator `\$` and the monadic bind. But that is only with the commonly used bind operator. There are versions of both operators with flipped arguments:

```(positionInAlphabet <=< firstChar) =<< (Just "Hurray")
-- returns: Just 8
-- returns: [1,43,2,44,2,44,4,46,3,45,6,48]
```

These, in my opinion more consistent versions, are not commonly used, but at least they exist. It is worth mentioning though, that `>>=` is in prelude, while `=<<` is only in Control.Monad.

There is one more function which must be defined for every monad and which I didn’t mention yet. It is `return` and its type is ```Monad m => a -> m a```. So for any value, `return` gives you the value mapped to a monadic functor. So this is basically a generic version of a type constructor for monads. There are at least two reasons why this is needed:3

1. It allows us to write polymorphic functions which can operate on any monad.

2. It allows the creator of a monad, to do fancy stuff on the creation of a monadic value.

# An example of state

Now that we have a first impression what monads are, and why they are useful. But what’s all the fuss about them being so powerful? Monads are able to solve all the problems with pure functional programming, like side effects and state, how is this possible?

The answer is, that functors can enhance, or embellish, values. Taking our picture of containers, think about putting extra notes on the container, or even equip the container with some elaborated machinery, which does fancy thing, each time the content of the container is changed…

I’ll end with an relatively simple example of such a monad: The task will be to log changes on a value. So we will have functions that not only operate on the value but in addition create messages. These messages shall be aggregated, so that, together with the final result after an arbitrary number of operations, we will also have a complete log of all operations performed.4

So lets define our new monad `Logger`:

```module Logger (Logger(..), showLog)
where

import Control.Applicative (Applicative(..))

data Logger a = Logger {value :: a, logs :: [String]}
deriving Show

instance Functor Logger where
fmap = liftM

instance Applicative Logger where
pure x = Logger x []
(<*>) = ap

return = pure -- redundant since GHC 7.10 due to default impl
(Logger x ls) >>= f = let (Logger r l) = f x in
Logger r \$ ls ++ l

showLog :: Logger a -> String
showLog = unlines . logs
```

There are a few things to say about the code, basically all the magic happens in the definition of `>>=`: The logging text, which is already part of the container of the argument is merged with the logging text, which the function `f` provided with its result.

What might be confusing are the other instance definitions:

• `Functor`: as monads are functors it comes as no surprise that we must implement `fmap`. The good thing: `fmap` can be defined in terms of the monadic functions,5 which is already done by Control.Monad, where it is called `liftM` (because it “lifts” the function into the monad), so we can simply use that.

• `Applicative`: I have not written about applicative functors yet, and for now we can basically ignore them, but we have to define the instance as just like functor it’s a super class of monad. There are two mandatory functions which we must supply:

• `<*>`, which again we can define it in terms of a function from Control.Monad

• and `pure` which happens to be identical to `return`. Because Haskell’s default definition of `return` in the `Monad` class is `pure` it makes sense to define `pure` instead of defining `return` directly, it’s the same thing anyway.

The function `showLog` is just a convenience function I added for a nice output of the logging information.

Now lets write a small program, using our new monad:

```import Logger

type Account = Logger Int

newAccount :: Int -> Account
newAccount n = Logger n ["Initial balance: " ++ show n ++ " Credits"]

modifyAccount :: Int -> Int -> Account
modifyAccount n old = Logger (old + n) msg
where
msg
| n > 0 = ["Deposited " ++ show n ++ " Credits"]
| n < 0 = ["Withdrew " ++ show (negate n) ++ " Credits"]
| otherwise = ["Null operation"]

-- Use it:
main :: IO ()
main = do
let account = newAccount 0
>>= modifyAccount 42
>>= modifyAccount (-23)
>>= modifyAccount 256
>>= modifyAccount 25
putStrLn \$ "Current balance: " ++ (show . value \$ account)
putStrLn "Account's History:"
putStrLn \$ showLog account
```

When run, it produces the output:

``````Current balance: 300
Account's History:
Initial balance: 0 Credits
Deposited 42 Credits
Withdrew 23 Credits
Deposited 256 Credits
Deposited 25 Credits
``````

So what we achieved here, is a behavior as if the log was some kind of global variable (or global state) each call of `modifyAccount` appended its logging information to.

The `main` function of the example shows something else, namely why the default bind operator `>>=` has its merits: consecutive functions combined by bind can be understood as a series of “actions”, and in this sense its easier to read code, where the order of execution and the order of actions (functions) in the code are identical.

I have left out a lot of (partly important) details (and interesting theory) in this article. Now that I hopefully have shown to you, that monads in practice are nothing extraordinarily hard to understand, I’d highly recommend to study the work by others, to get a more complete picture of the topic:

• as with any topic related to category theory my first recommendation will be Category Theory for Programmers by Bartosz Milewski. You can read it on his Blog or watch it as ongoing series of talks, given by him self on YouTube.

• being an essential part of Haskell, there is a lot of material in the Haskell Wiki on monads

• The Department of Computer and Information Science (CIS) of the University of Pennsylvania has a nice summary on monads and especially the IO monad in their Haskell course

# Comment

As always, I’d like to hear from you. Especially I would be interested if this article helped you with understanding monads in Haskell or just increased the confusion…

# Kudos

I want to thank Bernhard Herzog for corrections and suggestions.

1. The other three monad laws are part of the formal definition of a monad, you can learn about them e.g. in the Haskell Wiki

[return]
2. Note, only the type of the “container” (the functor) needs to match, not the type of the “content”.

[return]
3. There are much more profound reasons for `return`, but like all the other deeper theoretical stuff, smarter people than I am already have explained them much better than I ever could. See the Learn more section of this article.

[return]
4. Basically I nicked the idea from Bartosz Milewski’s lecture on Kleisli categories, which is no coincidence, as Kleisli categories are basically monads.

[return]
5. e.g. `fmap f = (=<<) (return . f)` [return]