Bonus: The M Word

Were you expecting to see monads in this book? If so, you won’t be disappointed. :)

Almost all of the data types I showed in this book are monads. This includes Option, Try, Either, List, Seq, Vector, IO, and ZIO: they’re all monads, or what we call monadic data types.

I won’t get into mathematical theory here, but in Scala, a monad is primarily a data type that properly implements map and flatMap methods so that it can be used in for expressions. There’s a little more to it than that, but from an implementation standpoint, that’s the big thing. As I’ve shown, you can use flatMap to run a few effects in sequence, and for expressions to run many effects in sequence.

And as I show in Functional Programming, Simplified, for expressions are syntactic sugar that compile down to a series of flatMap calls followed by a single map call.

Sequential composition

The key about monads in any language is that they allow you to guarantee that effects will occur in order (i.e., sequentially). For example, Haskell is a lazy (or lazily evaluated) programming language, and part of what that means is that whenever the Haskell compiler sees that it can run expressions in parallel, it might just do that.

However, when you prompt a user for input, like this:

print("Your input: ")

you really want to make sure that your “prompt the user” code occurs before your “read their input” code:

val input = readInput()

To make any sense, those operations must occur in that order, one after the other. In Haskell, you use its do construct to ensure that expressions are run in sequence, and in Scala you similarly sequence them in for expressions, like this:

    _     <- promptUser()
    input  = readInput()
    // more code here ...

If you recall that the ZIO type is a “blueprint for describing a concurrent workflow,” you should think, “If promptUser and readInput run concurrently, I need to use a for expression or flatMap to make sure those two functions are called in the proper order.”

For this reason, some people refer to monads as the “semi-colon in FP.” They let us run our effects in a guaranteed sequence, so even if our functions are meant to run in parallel, flatMap and for expressions guarantee that they’re run in sequence, just like procedural code.

Monads in Scala

But again, the key in Scala is that these monadic data types properly implement the map and flatMap methods inside their classes, and this is what enables them to be used in for expressions. I write about this in great detail in these two resources:

Category Theory

For those who are interested in the theory behind names like monad, monoid, functor, and other FP terms with unusual names, the next thing you’ll want to dig into is category theory (which is where the name “Cats Effect” comes from).

You can find a free version of a book named Category Theory for Programmers at these locations:

As I’ve shown in this book, you don’t need to understand category theory to understand FP, but when you want to know where names like “map” come from, category theory is what you’re looking for.