|
|
|
|
|
by tosyx
4332 days ago
|
|
I like to think of Applicative Functors, Monads, etc as the Design Patterns of functional languages (though I've developed most of my understanding by applying these ideas in JavaScript). A nice way to think about how they can be used (and the difference between parallel and sequential evaluation discussed towards the end of the article) is in handling promises: The parallel or sequential composition of a list of promises returns a promise of a list. The monadic composition resolves each promise sequentially (via the Haskell operator `sequence` or as a cascade of JavaScript `.then` calls). The parallel applicative composition resolves all promises simultaneously. |
|
So, perhaps they're design patterns, but I think calling them that puts them on too high a pedestal. True "functional" design patterns I think are much deeper. They include things like recursion schemes and the Types of Data [1], module design, purely functional data structures, handling laziness and strictness, etc.
As others have stated, your parallel v. sequential composition model is murky because it conflates dependency time versus real time. This is not how Monads and Applicatives work or differ at all!
But they do operate in sequence and in parallel—it's in "dependency order" though.
If you think of monads and applicatives as being composed of "layers" of action where each action pairs some instruction (like "print this string") and a "next action slot" which can contain whatever we like then we can see how monads and applicatives differ.
In applicatives, you have a list of these layers—the first next-action-slot contains a function and the remaining elements in the list contain each parameter of the function in their next-action-slot. Applicatives are "executed" by running all of the actions in the list in sequence (weird right?) and then applying all of the arguments to the function.
In monads, you "stack" layers. By stack I mean we place a new layer in the "next action slot" of each layer so that to find the next action you have to keep digging down and down through the layers. This means that each later layer can depend upon results of the "action" performed at earlier layers given monads their "dependency" structure.
These analyses are known as the free monad and free applicative. I really encourage everyone study them if they're interested.
[0] http://hackage.haskell.org/package/bound [1] http://tel.github.io/2014/07/23/types_of_data/