I’ve been using Scala at work and to understand Functional Programming more deeply I picked Graham Hutton’s Programming in Haskell (love it :)
In the chapter on Monads I got my first look into the concept of Applicative Functors (AFs)
In my (limited) professional-Scala capacity I’ve never had to use AFs and have always written code that uses Monads. I’m trying to distill the understanding of “when to use AFs” and hence the question. Is this insight correct:
If all your computations are independent and parallelizable (i.e., the result of one doesn’t determine the output of another) your needs would be better served by an AF if the output needs to be piped to a pure function without effects. If however, you have even a single dependency AFs won’t help and you’ll be forced to use Monads. If the output needs to be piped to a function with effects (e.g., returning Maybe) you’ll need Monads.
For example, if you have “monadic” code like so:
val result = for {
x <- callServiceX(...)
y <- callServiceY(...) //not dependent on X
} yield f(x,y)
It’s better to do something like (pseudo-AF syntax for scala where |@|
is like a separator between parallel/asynch calls).
val result = (callServiceX(...) |@| callServiceY(...)).f(_,_)
- If
f == pure and callService* are independent
AFs will serve you better - If
f
has effects i.e.,f(x,y): Option[Response]
you’ll need Monads - If
callServiceX(...), y <- callServiceY(...), callServiceZ(y)
i.e., there is even a single dependency in the chain, use Monads.
Is my understanding correct? I know there’s a lot more to AFs/Monads and I believe I understand the advantages of one over the other (for the most part). What I want to know is the decision making process of deciding which one to use in a particular context.
do
construct, but then the compiler determines whether it can be desugared to use anApplicative
instance rather than aMonad
instance. The primary goal was to determine when the code could be safely parallelized; I'm not sure if there are any other compiler-level reasons to prefer one over the other. – chepner