Witchcraft v0.3.0 Witchcraft.Applicative protocol

Applicative functors provide a method of applying a function contained in a data structure to a value of the same type. This allows you to apply and compose functions to values while avoiding repeated manual wrapping and unwrapping of those values.

Properties

Identity

applying a lifted id to some lifted value v does not change v

apply(v, wrap(&id(&1))) == v

Composition

apply composes normally.

apply((wrap &compose(&1,&2)), (apply(u,(apply(v, w))))) == apply(u,(apply(v, w)))

Homomorphism

applying a wrapped function to a wrapped value is the same as wrapping the result of the function on that value.

apply(wrap x, wrap f) == wrap f(x))

Interchange

The order does not matter when applying to a wrapped value and a wrapped function.

apply(wrap y, u) == apply(u, wrap &(lift(y, &1))

Functor

Being an applicative functor, apply behaves as lift on wrapped values

lift(x, f) == apply(x, (wrap f))

Notes

Given that Elixir functons are right-associative, you can write clean looking, but much more ambiguous versions:

wrap(y) |> apply(u) == apply(u, wrap(&lift(y, &1)))

lift(x, f) == apply(x, wrap f)

However, it is strongly recommended to include the parentheses for clarity.

Summary

Functions

Sequentially apply lifted function(s) to lifted data

Lift a pure value into a type provided by some specemin (usually the zeroth or empty value of that type, but not nessesarily)

Types

t :: term

Functions

apply(wrapped_value, wrapped_function)

Specs

apply(any, (... -> any)) :: any

Sequentially apply lifted function(s) to lifted data.

wrap(specimen, bare)

Specs

wrap(any, any) :: any

Lift a pure value into a type provided by some specemin (usually the zeroth or empty value of that type, but not nessesarily).