Mark Elston (131) [Avatar] Offline
#1
In the sidebar on page 72 you implement the map2 function as:

a flatMap (aa =>
b map (bb =>
f(aa, bb)))

Why use flatMap here? Wouldn't map do just as well? In the previous discussion of map and flatMap (p. 65) the only thing you say about flatMap is that the function passed in can fail. Can't that happen with map as well? What is the difference between the two here?

Mark
Mark Elston (131) [Avatar] Offline
#2
Re: Question Section 4.3.2 on map2 implementation
OK. Answering my own question (for those who may have the same issue).

This took a long time for me to figure out as I may have missed something important in the previous discussion but when I ran across exercise 3 I *never* thought of using map/flatMap. Instead, I used match/case. It was trivial to implement and easy to understand. When I ran across the solution in the sidebar I puzzled over it for a long time before I saw what was happening.

First, the result of the 'outer' function must return an Option[C] so either map or flatMap would do the job for that. However, since both of these functions return an Option, only flatMap can work for the 'outer' level since the function it takes is expected to take an A (in this case) and return an Option.

That leaves the question of what to use for the 'inner' function. Since this directly calls the function being passed in, which returns a C (not an Option[C]), this *must* be the map function as this matches the definition for map.

This also indicates the general form (not using for-comprehension) of the question of map3, map4, etc. map3 would be implemented like:

def map3[A,BB,C,D] (a: Option[A], b: Option[BB], c: Option[C]) (f: (A, BB, C) => D) : Option[D] =
a flatMap (aa =>
b flatMap (bb =>
c map (cc => f(aa, bb, cc))))


In other words, all the enclosing function must be flatMap while only the inner function can be map.

(sorry about the BB above but without it I got inconsistent bolding in the message).

Mark
Mark Elston (131) [Avatar] Offline
#3
Re: Question Section 4.3.2 on map2 implementation
I thought I had been careful in my explanation but as I re-read it I found it confusing (sigh).

So, I will try again.

The function that map takes expects the base types (A, B, C, etc.) and returns one of the base types. But both map and flatMap return Option types. So, if map is used it can only be used at the inner-most level. In fact, it must be used at the inner-most level since we are wrapping a function that doesn't know about Option types and yet should ultimately return one.

So, the innermost (right-most?) function must be a map. However, since map returns an Option, and it is used as the function passed into the next (outer) function, that next function must be a flatMap, as it the function it takes must take the base types and return an Option.

Hopefully this is more understandable.

Mark