Understanding how **map** works is pretty easy. It doesn’t need a second thought. In the contrary **flatMap** usually needs a bit of thinking to realize/remember how it works. In this post I’ll try to give a schematic explanation of the difference of flatMap & map.

Basically, **map** & **flatMap** result to the same thing. They take a monad & return a monad with transformed values.

The difference between them lays in the transformation function. **Map’s** transformation function takes a **value** & returns a **value** where flatMap takes a **value** & returns a **monad** with the transformed value.

Now you will ask me why is it called **flatMap **then? Well .. it’s called **flatMap** because if you use **map** on a function that returns a **monad**, you get a “**double**” **monad** (see drawing below). So in that context, flatMap “**flattens out”** the result 🙂

And that situation (double monad) happens quite often! For example, if you have a *booking* that has an optional *user*. And the optional *user* has an optional *email*. And you want to write a method *getEmail()* that gives you the *email* option of a *booking*, how would you do it with **map**?

booking : Booking booking.user : Option[User] booking.user.email : Option[String] def getEmail(booking: Booking) : Option[String] = ???

If you use **map** for it, you’ll have to do something like that (mainly because booking.user.map(_.email) returns an Option[Option[String]]):

def getEmail(booking: Booking) = booking.user.map(_.email).getOrElse(None)

This is where **flatMap** becomes useful. Due to the fact that flatMap’s transformation function is returning a monad, we kind of right away get the inner monad!:

def getEmail(booking: Booking) booking.user.flatMap(_.email)

And that’s it! Do you get it now why is it called **flatMap**? Hope this blog post helps you remember it 🙂 Have a nice day!