Dec

2nd

Sun
2nd

## Monads as I understand them

To be honest, it took me a ton of tutorials - a ton - before I could look you in the eye and say I understand what the hell a monad is.I believe the reason for this is not because they are hard, but because all those tutorials didn’t build upon my basic understanding of functors. Functors are much easier to understand. If you need a refresher read this: http://drboolean.tumblr.com/post/25413244757/functor-i-hardly-knew-her

Or have a play with them yourself: https://github.com/loop-recur/typeclasses

In this post, I hope to take the quickest path to explaining monads without taking all the detours due to their vast usage and abstract nature.

## Why we have monads in the first place

What follows is our naive program. In a perfect world we could write this:

```
//+ getUser :: Number -> User
var getUser = db.find('users');
//+ parseUrl :: String -> Number
var parseUrl = compose(pluck(1), match(/users\/(\d+)/));
//+ urlToUser :: String -> User
var urlToUser = compose(getUser, parseUrl);
```

Our entry point is **urlToUser**. It will take a url string to parse and extract the id from then it will give that to

**getUser**to find our user.

I said this representation is naive because there are a few places we can fail. Let’s start with it failing on the

**parseUrl**function. This function may or may not find a match from our

**match(/users\/(\d+)/)**and it will blow up with a

*TypeError: Cannot read property ‘1’ of null*if it can’t!

This will never do. Since every monad is a functor and functors are easier to understand, lets start there. Functors to the rescue!

```
//+ getUser :: Number -> User
var getUser = db.find('users');
//+ parseUrl :: String -> Maybe(Number)
var parseUrl = compose(fmap(pluck(1)), Maybe, match(/users\/(\d+)/));
//+ urlToUser :: String -> Maybe(User)
var urlToUser = compose(fmap(getUser), parseUrl);
```

What we had to do is place our match result into a **Maybe**. This forces the rest of our code to deal with the fact that we may or may not have a match in

**pluck(1)**and

**getUser**.

The real thing to think about here is what we’ve done typewise. In

**urlToUser**, we’ve composed

**parseUrl :: String -> Maybe(Number)**with

**getUser :: Number -> User**. Those types shouldn’t line up since

**getUser**takes a

**Number**not a

**Maybe(Number)**. Through the magic of

**fmap**which opens up our

**Maybe**and runs the function on it’s innards, we pass our

**Number**to

**getUser**instead of the

**Maybe(Number)**and all is well.

You could say we composed these types:

**a -> F(b)**(parseUrl)

**b -> c**(getUser)

And ended up with:

**a -> F(c)**(urlToUser)

Where

**F**is the functor (in this case Maybe). K, great. We understand functors and all that, but what about monads?!

## Getting more robust

Well, we caught the first failure case, but there’s another one. What if

**getUser**doesn’t actually find a user?! Total code anarchy. Let’s catch this case now*:

```
//+ getUser :: Number -> Maybe(User)
var getUser = compose(Maybe, db.find('users'));
//+ parseUrl :: String -> Maybe(Number)
var parseUrl = compose(fmap(pluck(1)), Maybe, match(/users\/(\d+)/));
//+ urlToUser :: String -> Maybe(Maybe(User))
var urlToUser = compose(fmap(getUser), parseUrl);
```

Darn it. We wanted **urlToUser**to return a

**Maybe(User)**, but we returned a

**Maybe(Maybe(User))**. Since

**fmap**re-wraps up the type for us and

**getUser**returns a

**Maybe**too, we get a nested Maybe that we need to flatten.

*This is precisely the time to use a monad.*Luckily,

**Maybe**is a monad in addition to being a functor.

There is this great function called

**mjoin**that we need to use. It’s specific to each monad instance. For

**Maybe**it works like this:

```
mjoin(Maybe(Maybe("hello monad"))) // Maybe("hello monad")
mjoin(Maybe(Maybe(null))) // Maybe(null)
```

```
``````
//+ urlToUser :: String -> Maybe(User)
var urlToUser = compose(mjoin, fmap(getUser), parseUrl);
```

Boom! We just flattened the instance and we’re good to go. Congrats, you just used the **Maybe**monad! It was really that easy.

So back to types. We needed to compose

**parseUrl :: String -> Maybe(Number)**with

**getUser :: Number -> Maybe(User)**. This is exactly the pattern we want to recognize as monadic composition or in other words, composing two functions that take normal values, but return monadic values. Here’s the abstract pattern:

**a -> M(b)**(parseUrl)

**b -> M(c)**(getUser)

And ended up with:

**a -> M(c)**(urlToUser)

We used

**M**for monad in the types above instead of

**F**for functor since we’ll need the ability to call

**mjoin**on it afterwards to flatten it up.

## So monads are functors that flatten?

Well, yes…but it goes further than that. Just stay with me here as we go through the final trick.

If we wanted to compose lots of monadic functions it would get real awkward real fast since

**mjoin**only flattens our values once and we’d see a lot of

**compose(mjoin, fmap)**everywhere.

The real power of monads comes from our

**mbind**function. This function is defined as just the combination of

**fmap**and

**mjoin**as you would expect, but with a few quirks:

```
//+ mbind :: M(a) -> (a -> M(b)) -> M(b)
var mbind = function(mv, f) {
return compose(mjoin, fmap(f))(mv);
}
```

The first thing to notice is we’ve flipped the arguments to around (value, then function). This is because it’s setup for chaining/nesting. Check it out:
```
//+ addMaybes :: Maybe(Number) -> Maybe(Number) -> Maybe(Number)
var addMaybes = function(ma, mb) {
return mbind(ma, function(a) {
return mbind(mb, function(b) {
return Maybe(a + b);
});
});
}
addMaybes(Maybe(3), Maybe(4)) // Maybe(7)
addMaybes(Maybe(null), Maybe(4)) // Maybe(null)
```

This is just like our node.js “pyramid of doom” nested callback style. The reason that’s so powerful is that:**1. We can depend on the values from the previous expressions**

We get access to

**a**and

**b**to use together. We can keep

**mbind**-ing deeper and deeper and pretend as though all the values have succeeded and are there.

**2. We can prevent the nested functions from running all together**

If anything isn’t there, we’ll never reach the following function since

**Maybe**won’t even run it. And since the rest of the functions are nested the whole process gets shut down right then and there.

Both of these features are unique to monads and are what make a them more powerful than functors/applicatives. So use that when you’re making a decision on whether or not you need to use a monad or not. Usually it’s better to not use them if you can get away with something simpler.

## Lastly, …for now

There’s a whole lot of monad stuff to learn. I could talk about pointed functors and keeping it type generic by using

**mresult**, I could talk about

**mcompose**or

**ap**or the monoid instance

**MonadPlus**, but I wanted to point out one last little feature for now.

**liftM**

liftM keeps us point free and simple. It works just like

**fmap**, but for monads:

```
//+ addMaybes :: M(Number) -> M(Number) -> M(Number)
var addMaybes = liftM("+");
liftM(function(x){ return x + 1; }, Maybe(4)) // Maybe(5)
liftM(function(x, y){ return x + y; }, Maybe(4), Maybe(5)) // Maybe(9)
liftM(function(x, y){ return x + y; }, Maybe(4), Maybe(null)) // Maybe(null)
```

When **liftM**is given multiple arguments, it nests each value as if we were writing our

**mbind**manually.

So there you have it!

*Something to mention is that

**db.find**should probably return a

**Maybe(a)**by design. This would force us to deal with the nulls and make our program more robust from the start. If you contrast that to just returning null like we did in the previous example, you can see that these types really do help you write a more correct program.