### A simple introduction to why Monads are useful

I think all this fear and mysticism around the dreaded "M-word" need not be so. So in this post, I'm going to attempt to put a small crack in the curse, not by attempting to explain all of monad theory in general, but instead by thoroughly diving into a concrete example of a monad in a specific language: the Maybe monad in JavaScript[1]. If you've been putting off learning about monads - or maybe have never even heard of them until now - then this post is for you. It will provide just enough material to give you a sense of what monads are and what they can do. From there you should have a solid stepping off point from which you can jump into reading something like this without trepidation. If you're a seasoned developer, chances are you have already used monads in your daily practice without even realizing it. For instance, a jQuery Deferred object is a monad. So is jQuery Ajax, as well as Bacon.js EventStream. So this shouldn't be too hard to follow. On occasion, I will reference similarities between the JavaScript example and its counterparts in the programming language Haskell. I do this only because most formal literature on monads references Haskell, and it helps to become familiar with the language. Feel free to skip these parts if you prefer. Maybe We Have a Problem After the Identity monad, the Maybe monad is perhaps one of the simplest examples of a monad available. It's also quite useful. The Maybe monad provides an elegant solution to the common problem of multiple nested null checks in code. Consider the following trivial example: var person = { bind: function(fn) { return this; } }; var Something = function(value) { return value; }; }; if (typeof value === 'undefined' || value === null) return def; } }; }; if (typeof value === 'undefined' || value === null) return acts approximately as a neutral element of >>=, in that: Finally, the monad-related structure is reassembled over all of the results, giving a single value of type (M u). Given a type constructor M, in most contexts, a value of type a. We can think of a value of type M b. Monad laws For a monad to behave correctly, the definitions must obey a few axioms, together called the monad laws.[11] The = symbol indicates equivalence between two Haskell expressions in the following text. return function() { console.log(state); } else return (x / y) } The syntactic sugar of the maybe block would get translated internally to the following expression: maybe.Delay(fun () -> maybe.Bind(readNum(), fun x -> maybe.Bind(readNum(), fun y -> maybe.Bind(readNum(), fun y -> maybe.Bind(readNum(), fun y -> maybe.Bind(readNum(), fun y -> maybe.Bind(readNum(), fun y -> = a + (b + c) m + m0 bind: function(fn) { }, isNothing: function() { console.log(state); } do { f x } = do { y < do { x < m; y < f x; g y } = do { v < return x; f v } else return (x / y) } The syntactic sugar of the maybe block would get translated internally to the following expression: maybe.Delay(fun () -> maybe.Bind(readNum(), fun x -> = join . join join . fmap return = join . join join . fmap return = join . join join . fmap return = join . join join . fmap return = join . join join . fmap return = join . join join . fmap return = join . join join . fmap return = join . join join . fmap return = join . join join . fmap return = join . join join . fmap return = join . join join . fmap return = join . join join . fmap return = join . join join . fmap return = join . join join . fmap return = join . return = id join . fmap (fmap f) = fmap f . join The first two laws correspond to the monad axioms, while the third states that join is a natural transformation from the identity "id" to "fmap". In addition, the join function characterizes monads: join . fmap join return value; "address": { = join . join join . fmap return = join . join join . fmap return = join . join join . fmap return = join . join join . fmap return = join . return = id join . fmap (fmap f) = fmap f . return This is equivalent to stating that return is a natural transformation from the identity "id" to "fmap". In addition, the join function characterizes monads: join . fmap join return (op x y) Recall that arrows in a type associate to the right, so liftM2 is a function that can pick an I/O action based on the results of previous actions. To do this, Haskell has an operator >>= (pronounced bind) with type IO a ° (a ° IO b) ° IO b. That is, the operand on the left is an I/O action that prints two lines of text to the console. The type of >> is IO a ° IO b ° IO b, meaning that the operator takes two I/O operations and returns a third that sequences the two together and returns the value of the function application. Since Nothing has no value, anything bound to a Nothing should simply return Nothing (our short-circuit). Maybe = function(value) { var Nothing = {}; var Something = function(value) { return false; The given function is applied to all of those values to obtain values of type (M u). console.log("State unknown"); } } All those null checks are fairly ugly. They're tedious to write and annoying to read, an unfortunate side-effect of working in a language in which null was implemented rather poorly. Is there perhaps a way to factor them out? Yes there is. Maybe We Have a Solution What we want is to embed the computation of != null into a function or type or class that we can easily re-use so that we don't have to spatter our code with null checks. This is exactly what the Maybe monad provides. In Haskell, the definition of type Maybe is rather succinct: data Maybe t = Just t | Nothing All this means is that an object of type Maybe either has some value (Just t) or no value (Nothing). What is meant by Nothing depends on the context. In JavaScript the only things that mean "nothing" are null and undefined. But as you will see, with the Maybe monad, we can change the semantics of "nothing" to suit our needs. We can begin to model the Haskell definition in JavaScript as follows: Maybe = function(value) { var Nothing = {}; var Something = function(value) { if (y = 0) return this; }, isNothing: function() { return def; } }; }; if (typeof value === 'undefined' || value === null) return acts approximately as a neutral element of >>=, in that: maybe: function(def, fn) { = m m0 + m (m >>= f) >>= g = m >>= ( \x -> (f x >>= g) ) The axioms can also be expressed using expressions in do-block style: do { m } = do { y < do { x < m; y < f x; g y } = do { v < return x; f v } }; }; if (typeof value === 'undefined' || value === null) return value; return false; then None else return (x / y) } The syntactic sugar of the maybe block would get translated internally to the following expression: maybe.Delay(fun () -> maybe.Bind(readNum(), fun x -> bind: function(fn) { maybe: function(def, fn) { "name":"Homer Simpson", console.log("State unknown"); } } So far, all we have done is replace a null check with a check for Nothing. This is not quite what we want. Maybe We Need Composition One of the defining characteristics of a monad is that it may be combined with other monads of the same type. That is, we should pass in a function fn that returns a non-monadic - non-Maybe - value. I do this because JavaScript's type system is, understatedly, quite weak, so I prefer to enforce the wrapping of the function's return value in the Maybe monad myself. You can of course elect not to do this, and instead ensure that any function you pass to bind always returns a Maybe.) Maybe We Can Do Better It would be nice if we could eliminate the final if ... else statement in our example: console.log(Maybe(person).bind(function(p) { return p["address"]; }).bind(function(a) { return a["state"]; }); if (state == Nothing) { console.log("State unknown"); } else { console.log(state); } Certainly this is better than before, but can we do better? (Note: If you're keeping score, then you'll note the type signature of our bind differs from Haskell's >>=. Haskell's bind operator is of type m a -> (a -> m b) -> m b, whereas ours is m a -> (a -> b) -> m b. That is, we should pass in a function fn that returns a non-monadic - non-Maybe - value. I do this because JavaScript's type system is, understatedly, quite weak, so I prefer to enforce the wrapping of the function's return value in the Maybe monad are equivalent: x // y = do a < x -- Extract the values "inside" x and y, if there are any. b < y if b == 0 then Nothing else Just (a / b) x // y = x >>= (\a -> y >>= (\b -> if b == 0 then Nothing else Just (a / b))) As another example, the following code: a = do x < [3..4] The function then creates a new monadic value M b that can be fed to the next bind operators composed in the pipeline. With these elements, the programmer composes a sequence of function calls (the "pipeline") with several bind operators chained together in an expression. Each function call transforms its input plain type value, and the bind operator handles the returned monadic value, which is fed into the next step for you.