You’re probably already using Monads but you may not realise it. If you’ve called
flatMap on an
you’re playing with Monads. But what exactly are Monads and why do we use them?
In very simple terms a Monad has a
flatMap method and we use them for sequencing effectful operations e.g.
fetch a user based on her id; then fetch the orders associated with this user
What is a Monad?
A Monad is a Functor (it has a
map method) but it also has
flatMap is simply a combination of
Monads must obey certain laws. I don’t believe it’s necessary to fully understand these laws unless you’re writing your
own Monads so I won’t go into them here. You can read more on the cats website. At this stage you just need to know
Either (Scala 2.12+) can all be thought of as Monads
What do we use Monads for?
We use the flatMap method to sequence effectful operations. In simple terms “effectful” means the operations return
For comprehension is often used as syntactic sugar for
def fetchUser(id: Int): Option[User] = ???
def fetchOrder(user: User): Option[Order] = ???
// <- is just a shortcut for flatMap
user <- fetchUser(1)
order <- fetchOrder(user)
} yield (user, order)
We can always compose Functors but not necessarily Monads
What does this mean? It means that so long as we just make use of the map method, we can write generic code that can
handle any stack of Functors e.g.
Option[Future[String]] etc. However the moment we start
flatten we can no longer handle any Monad stack generically.
To understand why this is the case we need to think about structure. In the case of map we’re only changing the innermost type
Future[Option[String]] => Future[Option[Int]] so the only code that needs to be specific is the code to handle this innermost
type, maybe parseInt in this example. We don’t need anything specific to Futures and Options (the Functors).
flatMap we’re actually changing the structure of the Monad stack e.g. a
flatten call would
Seq[Option[String]] => Seq[String] so we need something which understands that a
None should not be included in the
List but a
Some should. We call this code a Monad Transformer
Lean about Monad transformers