Edit 16 Feb 2011: typo - thanks to Tobias Sauerwein for pointing out

Monads for Java/C++ programmers

When I first started to learn Haskell, monads appeared as mysterious, if not mystical, entities. Reading tutorials, I had the impression that without monads one could accomplish things as exciting as generating the Fibonacci sequence, yet anything more real required mastering the concept of a monad.

Understanding monads was supposed to be easy, but wasn't. Let the number of monad tutorials on the web serve as proof. As for writing monads, Yet Another Haskell Tutorial says "you will only need to learn to write your own monads if you want to become a super Haskell guru." Not too good, is it?

I believe monads are, in fact, not at all hard to use or write. On the contrary, the concept itself is pretty simple, I would even say "unsatisfying". After the initial "Eureka!" moment I ended up thinking: "so... is that it??". Despite this simplicity, monads are very powerful.

In this tutorial, which is addressed to people with an object-oriented programming background, I will try to explain the very concept of a monad. I will not show its full power (I'm not sure I realise it myself), instead my ambition is to give you some intuition, which will allow you to understand other tutorials that show many uses for monads, should you so wish. I guess that when you're new to Haskell, one of the impediments in understanding these tutorials can be a poor command of the language itself. My intention is that you shouldn't need to understand Haskell very well to understand this tutorial. To facilitate this, I provide Java code doing similar things to the Haskell code. There is one important thing to remember, though. Java and Haskell code are not equivalent conceptually - in Haskell, for example, classes mean something else. Please don't build your general Haskell intuition by thinking that the following Java snippets are equivalent to their Haskell counterparts.

Disclaimer: the level of formality in this tutorial is rather low. I prefered to avoid introducing too many rigorous terms, so that readers unfamiliar with Haskell or functional programming could concentrate on the subject matter.

What is a monad?

From the OO perspective, I would say that a monad is a design pattern. While any self-respecting mathematician would probably like to kill me right now, what I mean to say is that a monad is not a Haskell construct -- it is not an entity. It is a feature. Something can be or become a monad. Similarly in OOD, something can be a strategy - if a bunch of classes obey certain laws, they have a common interface, a common purpose, but different implementations, and you use a particular one depending on a context, you will call them a strategy.

What kind of design pattern is a monad? You can think of it as allowing you to do "more stuff" when sequentially executing, or chaining, functions.

The problem

Suppose you have to query one database (say LDAP) to get a user's id by name and then using that id to query another database (say SQL) to get the user's balance and see whether it's overdraft. In Java 5, dummy code doing this could be something like:

private int lookupLDAP(String name) {
    if ("Irek".equals(name)) {
        return 1;
    } else {
        throw new UserNotFoundException();
    }
}

private int lookupBalance(int id) {
    if (id == 1) {
        return -1000;
    } else {
        throw new BalanceNotFoundException();
    }
}

Let's do the same thing in a more "Haskellesque" fashion. Although you probably would never code like this in Java, let's do it anyway, as it may help us to understand what the Haskell code does.

First, let's introduce a type that will encapsulate the fact that the query can either return a valid value or return nothing:

public interface Maybe<T> {
    T value();
}

public class Just<T> implements Maybe<T> {
    private T i;

    public Just(T i) {
        this.i = i;
    }

    public T value() {
        return i;
    }
}

public class Nothing<T> implements Maybe<T> {
    public T value() {
        throw new IllegalStateException();
    }
}

Now let's use the type we defined above:

public class Account {
    public Maybe<Boolean> hasOverdraft(String name) {
        Maybe<Integer> id = lookupId(name);
        if (id instanceof Nothing) {
            return new Nothing();
        } else {
            Maybe<Integer> balance = lookupBalance(id.value());
            if (balance instanceof Nothing) {
                return new Nothing();
            } else {
                return isBelowZero(balance.value());
            }
        }
    }

    private Maybe<Integer> lookupId(String name) {
        if ("Irek".equals(name)) {
            return new Just(1);
        } else {
            return new Nothing();
        }
    }

    private Maybe<Integer> lookupBalance(Integer id) {
        if (new Integer(1).equals(id)) {
            return new Just(1000000);
        } else {
            return new Nothing();
        }
    }

    private Maybe<Boolean> isBelowZero(Integer i) {
        return new Just<Boolean>(i < i);
    }
}

The Haskell code, without a monad, isn't much better. The Maybe type has already been defined for us in the language prelude:

hasOverdraft name = case (lookupId name) of
                      Nothing -> Nothing
                      Just id -> case (lookupBalance id) of
                                   Nothing -> Nothing
                                   Just balance -> isBelowZero balance
lookupId name = case name of
  "Irek" -> Just 1
  _      -> Nothing   -- underscore means "anything else"

lookupBalance uid = case uid of
  1 -> Just (1000000)
  _ -> Nothing                             
    
isBelowZero balance = Just (balance < 0)                               

The problem is that we have a repeating pattern:

if query is
  nothing - return nothing
  else if query is
    nothing - return nothing
    ...

The solution

Wouldn't it be nice to say

public Maybe<Boolean> hasOverdraft(String name) {
    return isBelowZero(lookupBalance(lookupId(name)));
}

as if operations were always successful, and somehow magically let the computer worry about Maybe types? Well, in Haskell you can:

hasOverdraft name = return name >>= lookupId >>= lookupBalance >>= isBelowZero

This function works exactly the same as the one defined previously. It's just so much shorter and cleaner. The >>= operator takes care of Nothing cases for you.

How does it work? >>=

The >>= (pronounced bind) operator takes the result of the first action, does "some stuff" and passes the result into the second action. It is a composition of two functions: fmap and join, both provided for the most common types by the Haskell platform.

a1 >>= a2 = join (fmap a2 a1)

Every action takes an argument without a Maybe, for example a String representing the name, and returns a Maybe, for example Maybe Integer, representing the id.

Fmap does the actual job, it applies the action a1 to the value inside a2. But if a1 is Nothing, then it returns Nothing immediately:

    fmap _            Nothing       = Nothing    -- underscore means "whatever function"
    fmap someFunction (Just a)      = Just (someFunction a)

Take a look at a few examples:

> addTwo x = x+2
> fmap addTwo (Just 4)  
Just 6
> fmap addTwo Nothing
Nothing 

Now, the function addTwo takes an integer and returns an integer. This means it has no way to fail (or in other words, no way to yield Nothing). What we need is a function that takes an integer and returns Maybe integer:

> maybeAddTwo x = Just (x+2)
> maybeAddTwoThatFails x = Nothing
> fmap maybeAddTwo (Just 4)  
Just (Just 6)
> fmap maybeAddTwo Nothing
Nothing
> fmap maybeAddTwoThatFails (Just 4)
Just Nothing 

Just (Just 6)? Just Nothing? This is not quite what we want. We end up having Maybies stacked onto each other. This is the job of the join function -- it collapses two Maybies into one:

join Nothing         = Nothing
join (Just Nothing)  = Nothing
join (Just (Just x)) = Just x

So again, the >>= first applies your second action onto the first one and collapses Maybies, so you don't end up having them nested, no matter how many actions you chain.

return

What does return do below, then?

hasOverdraft name = return name >>= lookupId >>= lookupBalance >>= isBelowZero

Return is a way of wrapping a "regular" value with a monad. Remember that every action needs to return a Maybe, so the way to pass a name into lookupId is to wrap it with a Maybe value, specifically with Just. Could we write

hasOverdraft name = Just name >>= lookupId >>= lookupBalance >>= isBelowZero

then? Yes, it is sort of fine, it would do the job. If you use return, though, your code will work with any monadic type -- not only Maybe. So far we've only been talking about "Maybe as a monad". There are other types that have the monadic property. The State type allows you to pass state through the chain of execution. The IO monad allows you to use the external environment to read from the keyboard and display on the screen. There are many many more, plus you can write one yourself.

What the heck is a monad then?

A monad is any type that has >>= and return defined on it. >>= applies result of the first action onto the second action and makes sure you don't get nested types, return wraps a value with the type. It also needs to obey certain laws, but for now we can assume they obey common sense.

When would you use a monad? If you run functions in a specific order and you need to do "some stuff" in between, you want to use a monad.

Although the concept is in fact very simple, this simplicity has a great potential. The Maybe monad is one of the simplest monads out there and you should not get the impression that this is all monads can do. There are many more complex uses of monads. For example the Parsec parsing library relies on monads heavily.

Conclusion

Hopefully you now have a general feeling of what a monad can be. I hope this will allow you to study other monad tutorials which deal with the subject using less examples and higher degree of formality. If you have any comments or something is not clear, please do not hesitate to contact me.