Biraj Dhakal
Biraj Dhakal

Reputation: 107

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

Upvotes: 4

Views: 1607

Answers (3)

justinhj
justinhj

Reputation: 11306

I think about things like this step by step from the result.

Firstly you know you eventually want a value of type A and a value of type B to pass to the function f.

Where does the A come from? We can access it by mapping over oa.

We can take that A and do the same to get B. mapping over ob gives us a B.

If you type this out in your IDE you will see a type error, you have an option option instead of an option.

This happened because that first map wraps its response as an option but so does the inner map. So by changing the outer map to flatMap you flatten it again.

Upvotes: 0

SergGr
SergGr

Reputation: 23788

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.

Upvotes: 2

Luka Jacobowitz
Luka Jacobowitz

Reputation: 23502

If you add some syntactic sugar using a for-comprehension it suddenly becomes a lot more easy to read if you ask me:

def map2[A,B,C] (ao: Option[A], bo: Option[B])(f: (A,B) => C): Option[C] = for {
  a <- ao
  b <- bo
} yield f(a,b)

Basically, we want to extract the a and the b of our two options and then apply our function f to get a C. flatMap allows us to do just that, by using a function from an A to an Option[B]. map then allows us to apply our function f to transform (A,B)to C.

Upvotes: 2

Related Questions