I’ve been looking at and playing with monads in the last week or so, and I think I’m getting pretty close to understanding them. From what I’ve seen, here’s why it’s a valuable design pattern.
If you’re familiar with the GoF patterns, monads are like the Decorator pattern and Builder pattern put together, on steroids, bitten by a radioactive badger.
- monads decorate some core type with additional properties without changing the core type. For example, a monad might “lift” String and add values like “isWellFormed”, “isProfanity” or “isPalindrome” etc.
- similarly, monads allow conglomerating a simple type into a collection type
- monads allow late binding of functions into this higher-order space
- monads allow mixing arbitrary functions and arguments with an arbitrary data type, in the higher-order space
- monads allow blending pure, stateless functions with an impure, stateful base, so you can keep track of where the trouble is
A familiar example of a monad in Java is List. It takes some core class, like String, and “lifts” it into the monad space of List, adding information about the list. Then it binds new functions into that space like get(), getFirst(), add(), empty(), etc.
On a small scale, suppose there’s a code snippet you apply all over the place, like checking to see if a value is null. You can incorporate the null check into a little monad like Maybe — or better yet, return a Maybe that knows it’s null, avoiding null altogether. Then you can build or “lift” a value into the monad, and eliminate the repetitive code.
On a large scale, imagine that instead of writing a program, you just wrote a big Builder (as the GoF pattern), and the build() method at the end spat out whatever answer the program was supposed to produce. And that you could add new methods to your ProgramBuilder without recompiling the original code. That’s why monads are a powerful design model.