I looked at Functors and applicatives in the previous blog post. I always found the separation between wrapping a value (functor) and a function to be applied (applicative) to be artificial. What I usually need is to wrap some value (a primitive, an object or a function) and then apply it to some argument.
- If we are wrapping a value and the argument is a function, we should call the function argument on the value (like a functor).
- If we are wrapping a function, we should call this function on the argument (like an applicative).
In both cases we should return a wrapped value to allow chaining the future calls.
Applier
I call the wrapped value in this case an Applier. Here is an applier "constructor" function.
1 | function Applier(value) { |
This is not real constructor function: Applier
is only meant to be a closure to keep value
private.
Here are typical use cases. There is always a single argument.
1 | Applier('foo')(length)(console.log); // prints 3 |
Because applier keeps returning itself, I need to be able to get to the result (wrapped value). I can do this by returning the wrapped value when the applier is called without arguments.
1 | function Applier(value) { |
Applier is chainable, thus I can build a chain of functions before an argument is known.
1 | var lengthOf = Applier(length); |
Maybe applier
We can add conditions into applier. For example to prevent calling function on undefined value, we can create Maybe applier.
1 | function Applier(value, conditions) { |
Typical use for MaybeApplier is to guard against calling a function on an undefined or null value
1 | function length(x) { |
conclusion
Appliers seem to erase the difference between functions and values. In my next blog post I will see how to connect appliers to functional pipelines.