Programming in Scala”
fpiscompanion
fpiscompanion
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
Chapter notes 38<br />
Notes on chapter 12: Applicative and traversable<br />
functors<br />
The cost of power<br />
There is a tradeoff between applicative APIs and monadic ones. Monadic APIs are strictly more<br />
powerful and flexible, but the cost is a certa<strong>in</strong> loss of algebraic reason<strong>in</strong>g.<br />
The difference is easy to demonstrate <strong>in</strong> theory, but takes some experience to fully appreciate <strong>in</strong><br />
practice.<br />
Consider composition <strong>in</strong> a monad, via compose (Kleisli composition):<br />
val foo: A => F[B] = ???<br />
val bar: B => F[C] = ???<br />
val baz: A => F[C] = bar compose foo<br />
There is no way that the implementation of the compose function <strong>in</strong> the Monad[F] <strong>in</strong>stance can<br />
<strong>in</strong>spect the values foo and bar. They are functions, so the only way to “see <strong>in</strong>side” them is to<br />
give them arguments. The values of type F[B] and F[C] respectively are not determ<strong>in</strong>ed until the<br />
composite function runs.<br />
Contrast this with comb<strong>in</strong><strong>in</strong>g values with map2:<br />
val quux: F[A] = ???<br />
val corge: F[B] = ???<br />
val grault: F[C] = map2(quux, corge)(f)<br />
Here the implementation of map2 can actually look at the values quux and corge, and take different<br />
paths depend<strong>in</strong>g on what they are. For <strong>in</strong>stance, it might rewrite them to a normal form for improved<br />
efficiency. If F is someth<strong>in</strong>g like Future, it might decide to start immediately evaluat<strong>in</strong>g them on<br />
different threads. If the data type F is applicative but not a monad, then the implementation has this<br />
flexibility universally. There is then never any chance that an expression <strong>in</strong> F is go<strong>in</strong>g to <strong>in</strong>volve<br />
functions of the form A => F[B] that it can’t see <strong>in</strong>side of.<br />
The lesson here is that power and flexibility <strong>in</strong> the <strong>in</strong>terface often restricts power and flexibility <strong>in</strong><br />
the implementation. And a more restricted <strong>in</strong>terface often gives the implementation more options.<br />
See this StackOverflow question¹⁶⁴ for a discussion of the issue with regard to parsers.<br />
See also the end of the note below on “Applicative laws”, for an example of the loss of algebraic<br />
reason<strong>in</strong>g that comes with mak<strong>in</strong>g an API monadic rather than applicative.<br />
¹⁶⁴http://stackoverflow.com/questions/7861903/what-are-the-benefits-of-applicative-pars<strong>in</strong>g-over-monadic-pars<strong>in</strong>g