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!