HOME - BLOG POSTS - TYPELEVEL CATS

# What is a Monad?

- 2 minutes read - 410 wordsYou’re probably already using Monads but you may not realise it. If you’ve called `flatMap`

on an `Option`

or `Future`

you’re playing with Monads. But what exactly are Monads and why do we use them?

*Monad*has a

`map`

and `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 `flatten`

and `flatMap`

methods
(`flatMap`

is simply a combination of `map`

and `flatten`

).

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
that `Future`

, `Option`

, `List`

and `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
monads i.e. `Future[String].flatMap(...): Future[A]`

For comprehension is often used as syntactic sugar for `flatMap`

calls:

```
def fetchUser(id: Int): Option[User] = ???
def fetchOrder(user: User): Option[Order] = ???
// <- is just a shortcut for flatMap
for {
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. `List[Option[String]]`

, `Option[Future[String]]`

etc. However the moment we start
to use `flatMap`

or `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
i.e. `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).

However with `flatten`

or `flatMap`

we’re actually changing the structure of the Monad stack e.g. a `flatten`

call would
transform `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

### What next?

Lean about Monad transformers