You'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?

**TL;DR**- In very simple terms a Monad has a

`map`

and `flatMap`

method and we use them for sequencing 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 (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] = ???
// for comprehension is just map/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