scalafunctional-programming

map2 in scala in Exception Handling


def map[B] (f: A=>B) : Option[B]

def flatMap[B] (f: A=>Option[B]) : Option[B] 

def map2[A,B,C] (ao: Option[A], bo: Option[B]) (f: (A,B) => C) :Option[C] =
ao.flatMap(aa=>
  bo.map(bb=>
    (f(aa,bb))))

Here is the definition of map and flatMap in Exception Handling and I have this map2 formed on the basis of map and flatMap. It is really hard to understand the formation of map2. Can some one explain the role of flatMap and map in map2. Thank you


Solution

  • Here is another attempt at explaining it. Option is a Monad which in a simplified way might be seen as a generic container that hold some value(s).

    map is a transformation operation that allows you to transform value(s) inside the monad using simple function on "raw" types.

    flatMap is similar to map but is a bit more complicated: it allows you to transform value(s) inside the monad using a function that accepts "raw" value but returns an instance of the same monad and still as a result you get just a Monad[B] instead of Monad[Monad[B]] that would be generated by the map. In other words flatMap "flattens" the result.

    So now what your map2 does? It accepts 2 instances of Option monad and a function that transform "raw" pair of types into a single new "raw" type and return Option of that result type. Logically this is similar to map but to implement it you need a flatMap. To call your f you need to "unpack" both ao and bo. But monad doesn't provide a way to just "unpack" raw value. You might want to use just map. After all map2 is logically similar to it! However, if you write

    ao.map(aa =>
      bo.map(bb => f(aa,bb)))
    

    as you might naively do, it wouldn't work as you might expect. The reason is that bo.map(bb => f(aa,bb)) returns Option[C] (remember, there is no standard way to "unpack" a monad) and thus your function passed to ao.map(aa => ...) returns Option[C] and thus the result would be Option[Option[C]]. But this exactly where flatMap comes to the rescue! It allows you "unpack" this double Option into a simple Option[C].

    Obviously this explanation is quite naive but I hope it will help you get some intuition about what happens.