bbarrington (25) [Avatar] Offline
#1
I'm not sure if this is the right place to be asking this question, but I'm having a really hard time wrapping my head around the differences between The Parser Monad & Parser Applicative that are discussed in section 12.3.2 of the book - specifically, the differences between map2 and flatMap. I went on to read the Chapter Notes in the hopes that I would gain further understanding, but I'm afraid I'm hopelessly lost at this point. Maybe someone can help.

In particular, please reference the two quotes from the Chapter Notes (Chapter 12) below. The first comes from the section 'The Cost of Power' and the second is at the end of the section on 'Applicative Laws'.

So how could the implementation of map2 change the resulting values from the expressions that were handed to it? If it did, then certainly the result of the map2 computation could change, could it not? And why is map2 special in this regard? Can't flatMap similarly 'look' at the value passed to it?

Don't the results of each of the functions passed into map2 & flatMap 'depend' on the arguments passed to them?

Seems to me like the Parser example in the book has a lot more to do with the return type of the functions. Certainly you could have an expression with a result of type Parser[Parser[Row]] passed as one of the arguments to map2. But then getting from a Parser[Row] to List[Row] would be problematic. In the flatMap case, getting from Parser[Row] to Parser[List[Row]] is natural and easy.

So I know I'm missing something really fundamental here. Hoping someone can help steer me in the right direction.

Thanks.

Here the implementation of map2 can actually look at the values quux and corge, and take different paths depending on what they are. For instance, it might rewrite them to a normal form for improved efficiency. If F is something like Future, it might decide to start immediately evaluating them on different threads. If the data type F is applicative but not a monad, then the implementation has this flexibility universally. There is then never any chance that an expression in F is going to involve functions of the form A => F[B] that it can't see inside of.


Note that this reasoning is lost when the applicative happens to be a monad and the expressions involve flatMap. The applicative laws amount to saying that the arguments to map, map2, map3, etc can be reasoned about independently, and an expression like flatMap(x)(f) explicitly introduces a dependency (so that the result of f depends on x). See the note above on "The cost of power".