Skip to content

Instantly share code, notes, and snippets.

@carlfish
Last active February 3, 2018 23:21
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save carlfish/6b9761670a131f821ad5 to your computer and use it in GitHub Desktop.
Save carlfish/6b9761670a131f821ad5 to your computer and use it in GitHub Desktop.
Why understanding monads is important.

Either and Promises/Futures are useful and I’ll use them next time they’re appropriate. But outside Haskell does their monad-ness matter?

(All code below is written in some made-up Java-like syntax, and inevitably contains bugs/typos. I'm also saying "point/flatMap" instead of "return/bind" because that's my audience. Any correspondance with anything that either be programatically or mathematically useful is coincidental)

What is a monad? A refresher.

A monad is something that implements "point" and "flatMap" correctly.

I probably just made a mathematician scream in agony, but bear with me on this one. Most definitions of monads in programming start with the stuff they can do like sequence computations, thread state through a purely functional operation, or allow functional IO. This is like explaining the Rubiks Cube by working backwards from how to solve it.

A monad is something that implements "point" and "flatMap" correctly.

So if this thing implements point and flatMap correctly, why do I care it's a monad?

Because "correctly" is defined by the monad laws.

  1. If you put something in a monad with point, that's what's in the monad. point(a).flatMap(f) === f(a)
  2. If you pass flatMap a function that just puts the same value in another monad instance, nothing happens. m.flatMap(a -> point(a)) === m
  3. You can compose multiple flatMaps into a single function that does the same thing. m.flatMap(f).flatMap(g) === m.flatMap(a -> f(a).flatMap(g))

If you don't understand these laws, you don't understand what flatMap does. If you understand these laws, you already understand what a monad is.

So saying "Foo implements flatMap correctly" is exactly the same as saying "Foo is a monad", except you're using eighteen extra characters to avoid the five that scare you.

Because being a monad gives you stuff for free.

If you have something with a working point and flatMap (i.e. a monad), then you know that a correct implementation of map() is map(f) = flatMap(a -> point(f(a)), because that's the only possible outcome that the monad laws allow.

You also get join(), which flattens out nested monads: join(m) = m.flatMap(a -> a) will turn Some(Some(3)) into Some(3).

You get sequence(), which takes a list of monads of A, and returns you a monad of a list of A's: sequence(l) = l.foldRight(point(List()))((m, ml) -> m.flatMap(x -> ml.flatMap(y -> point(x :: y)))) will turn [Future(x), Future(y)] into Future([x, y]).

And so on.

Because how do you know it implements flatMap correctly?

If something has a flatMap() but doesn't obey the monad laws, developers no longer get the assurance that any of the things you'd normally do with flatMap() (like the functions above) will work.

There are plenty of broken implementations of flatMap out there, possibly because people shy away from the M-word. Calling things what they are (is a monad, isn't a monad) gives us a vocabulary to explain why one of these things is not like the other. If you're implementing a flatMap() or its equivalent, you'd better understand what it means to be a monad or you'll be lying to the consumers of your API.

In summary

As developers, we do a better job when we understand the abstractions we're working with, how they function, and how they can be reused in different contexts.

Think of the most obvious monads that have started showing up in every language over the last few years: List, Future, Option, Either. What do they all have in common? Option and Either kind of do similar things, but not really. An Option is kind of like a zero-or-one element list, but not really. And even though Option and Either are kind of similar, and Option and List are kind of similar, that doesn't make Either and List similar in the same way at all! And a Future, well, er…

The thing they have in common is they're fucking monads.

@almassapargali
Copy link

Could you please add a brief introduction to what is point at the beginning?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment