The USS Quad Damage

Monads for Java programmers

I try and translate the value of monads from the wild and crazy world of Functional Programming to the rough and tumble world of Java programming.

I’ve had about three goes at understanding monads. The first alone, the second via some category theory training at work, and the third via this tutorial. While each of the three approaches has helped me understand what’s going on, the monad tutorial is probably the best bang for buck. It’s quick and easy to understand.

One thing I’m aware of is that everyone who has tried to learn category theory has written a monad tutorial. There’s a joke going around that it only demonstrates their understanding of Monads, and doesn’t help anyone else. I’m going to attempt to buck that trend by explaining monads by using Java, and the terminology of traditional OO programming.

So firstly, the thing to understand is that Monads are a design pattern. Ultimately, what they are about is solving a design problem, in the same way as Interfaces, Factories, or Builders solve design problems. The difference is that usually these design patterns are about layering software, and abstracting responsibilities. Monads, however, are about abstracting side-effects. I think programming as a discipline has seen how important that is, so let’s have a look at how Monads solve this problem:

interface Monad<I>
{
    <O> Function<Monad<I>, Monad<O>> wrapFunction(Function<A, Monad<O>> fun);
    Monad<I> wrapValue(I val);
}

Before I continue, I’m doing my best to represent the Monad pattern in a “natural” way in Java. In languages with more advanced type systems, the same “code” above will actually be far more powerful, but even in Java-land, this is quite a useful pattern. Also, the Function definition is from Guava. I hope you’re familiar with it.

The above Interface will look odd to start with. After all, why have these “wrap” functions on an interface? What’s the interface for? How do you use it? How does one even remotely abstract side-effects with this? The answer is: Category Theory. At this point I wave my hands about and say “WOOOO” and everyone’s really impressed with how smart I am. Seriously, though, the theory is clever trickery but when you actually work with it in practise it’s pretty straight forward.

People talk about Monads as “boxes”, and that’s an apt metaphor, but be careful, these are mathsey-boxes, so the metaphor will break down easily (there’s no unwrap!), and the value of them is not in the wrapping and unwrapping anyway. Note that these don’t work at all like the Proxy or the Facade design patterns, which you can kind of think of as “boxes”.

In order to demonstrate its use, I’m going to create a UselessMonad:

class UselessMonad<I> implements Monad<I>
{
    I val;

    I unwrapVal() {
        return this.val;
    }

    <O> Function<UselessMonad<I>, UselessMonad<O>> wrapFunction(Function<I, UselessMonad<O>> fun) {
        return new Function<UselessMonad<I>, UselessMonad<O>> {
            UselessMonad<O> apply(UselessMonad<I> a) {
                fun.apply(a.val);
            }
        }
    }

    UselessMonad<I> wrapValue(I a) {
        return new UselessMonad<I>(a); // Pretend there's a constructor.
    }
}

Note: I’ve skipped public final etc. etc. for brevity. Note also that the Interface types are now UselessMonad. I did that so that the type signatures are clear in the Monad interface above, but you should know how to change things so that the cast isn’t required.

OK, So this basically wraps a function and a value so that they are “boxed” in a UselessMonad. So far, this should look... odd... but not “difficult”. You should hopefully also notice that you can do this:

UselessMonad<String> v = new UselessMonad<String>();

Function<String, UselessMonad<String>> sayHello = ...;

String val = v.wrapFunction(sayHello).apply(v.wrapValue("world")).unwrapVal();

OK First let’s talk about the v jiggery-pokery I’ve done. In Java, you can only put an interface on an instance. Unfortunately, we want to put those interface methods to be static. Since we can’t do that, this is a hack to get around it.

Next, I want to talk about the slightly strange signature of sayHello. I mean, why would a function like that return a UselessMonad? And also, what if a function just returned a String and not a UselessMonad? Well, you can just construct a Function from another Function!

Function<I, UselessMonad<O>> uselessOf(Function<I, O> fun) {
    return new Function<I, UselessMonad<O>>() {
        UselessMonad<O> apply(I a) {
            return v.wrapValue(fun.apply(a));
        }
    };
}

To put it into words: You can take a Function that takes an A and returns a B, and create another Function that takes an A and returns a UselessMonad<O>, by calling wrapValue() on the result of the function. Before we continue down the rabbit hole, I just want to make it clear that it’s easy to generate functions that return the “Monad” version of a value from “normal” functions.

OK, so what does that wrapFunction line way up above actually do? Well, it does the equivalent of the following:

String val = sayHello.apply("world").unwrapVal();

So why write all that wrapping and unwrapping cruft if all you want to do is apply a Function? Well, the magic trick above is that the input and output of the function are both boxes! What this means is that you can write:

Function<String, String> howYaDoin = ...;

String val = v.wrapFunction(uselessOf(howYaDoin)).apply(
    v.wrapFunction(sayHello).apply(v.wrapValue("world"))).unwrapVal();

I’ve thrown in a uselessOf in there for good measure. Hopefully it doesn’t make things too confusing. Nice, right? I mean, it looks like a dog’s breakfast, but the good thing is that you can just keep wrapping functions till the cows come home. This is the whole point of the Monad! You go to all this trouble of functions that return functions and wrapping functions and the crazy signatures just so you can do this wrapping and applying and wrapping and applying.

But how does this help abstract away side effects?

Well, imagine your Monad wasn’t actually useless. Imagine it was something like Guava’s Optional:

class Optional<I> extends Monad<I>
{
    // Imagine the rest of Optional code here.
    <O> Function<Monad<I>, Monad<O>> wrapFunction(Function<I, Monad<O>> fun) {
        return new Function<Monad<I>, Monad<O>> {
            Monad<O> apply(Monad<I> val) {
                if (val.isPresent()) {
                    return fun.apply(val.get());
                }
                return absent();
            }
        };
    }

    Monad<I> wrapValue(I val) {
        return Optional.of(val);
    }
}

This means you can call code like:

Optional<String> val = v.wrapFunction(optionalOf(howYaDoin)).apply(
    v.wrapFunction(maybeSayHello).apply(v.wrapValue("world")));

Now, we can see the Monad in action: it allows you to chain up commands that return an Optional without having to constantly check for null, even though the howYaDoin function doesn’t expect a null as its input, and even though the maybeSayHello function might return absent(), it all just works. What’s even better is that this isn’t just true of Optional, but things like Futures, Lists, Logging, Transactions, etc. can all be written and composed in this way. A few more things to note here are that the “side-effects” of what’s Optional and what’s not are written in a completely type-safe way. You can’t accidentally do something silly like pass an Optional value somewhere where it’s not expected. There’s also a clear separation of concerns between the side-effects of potentially failing functions, and the actual main flow of the code. This is the problem that Monads solve.

Another important note: You might, as you’re writing Functions and things, get to a point where you have a Monad<Monad<I>>. Another important property of Monads is that you can take a nested structure of monads and create a single one:

Monad<I> flatten(Monad<Monad<I>> m) {
    m.wrapFunction(new Function<Monad<I>, Monad<I>>() {
        Monad<I> apply(Monad<I> a) {
            return a;
        }
    }).apply(m);
}

Again, you need to liberally sprinkle more generics on there, but the idea is correct. This is slightly magical as well, but basically it takes a function that just returns the value that it’s given, wraps it so the input will be a Monad<Monad<I>>, and will return a Monad<I>.

That’s all kind of neat, but for the Optional case, why not just do:

Optional<String> val = Optional.of("world").transform(maybeSayHello).transform(howYaDoin);

The short answer is: Yeah, that’s probably the smarter way. In languages like Haskell the Monad has significantly more power than in Java, so Monad is clearly the more attractive solution there. However, in Java, Guava’s chaining approach is pretty good. There are cases where the Monad way will result in less boilerplate code, but it’s probably not worth the added complexity. This is especially true if you look at all those wrappings occurring everywhere!

In conclusion, hopefully now you have a hands-on understanding of what a Monad is and where you might want to use it. It has limited usefulness in Java, but nevertheless is a very powerful design pattern. Keep in mind that this tutorial is not meant to cover the category theory and all the requirements of the design pattern (such as the Monad Laws, which you must not break), nor does any of this code compile. It’s probably worth writing this code in a way that is type-safe and compiles, and having a play with Monads. They are a very powerful pattern and once you get the hang of them you’ll see uses for them all over the place.