I am excited for this for two reasons. Potentially better performance and that some things that can't fit into the Monad pattern can fit into the Applicative Functor pattern.
In order to support the already existing let!
one need to implement Bind
and Return
, ie the Monad pattern.
let!
and and!
requires Apply
and Pure
(not exactly sure what F# the equivalent are named), ie the Applicative Functor pattern.
Applicative Functors are less powerful than Monads but still very useful. For example, in parsers.
As mentioned by Philip Carter, Applicative Functor can be made more efficient than Monads as it's possible to cache them.
The reason is the signature of Bind
: M<'T> -> ('T -> M<'U>) -> M<'U>
.
One typical way you implement bind is that you "execute" the first argument to produce a value of 'T
and pass it the second argument to get the next step M<'U>
which you execute as well.
As the second argument is a function that can return any M<'U>
it means caching is not possible.
With Apply
the signature is: M<'T -> 'U> -> M<'T> -> M<'U>
. As neither of the two inputs are functions you can potentially cache them or do precomputation.
This is useful for parsers, for example in FParsec
for performance reasons it's not recommended to use Bind
.
In addition; a "drawback" with Bind
is that if the first input doesn't produce a value 'T
there is no way to get the second computation M<'U>
. If you are building some kind of validator monad this means that as soon as a valid value can't be produced because the input is invalid then the validation will stop and you won't get a report of the remaining input.
With Applicative Functor you can execute all validators to produce a validation report for the entire document.
So I think it's pretty cool!