package selective

  1. Overview
  2. Docs
Module type
Class type
include Base.Applicative.Basic
type 'a t
val return : 'a -> 'a t
val apply : ('a -> 'b) t -> 'a t -> 'b t

The following identities ought to hold for every Applicative (for some value of =):

  • identity: return <*> t = t
  • composition: return Fn.compose <*> tf <*> tg <*> tx = tf <*> (tg <*> tx)
  • homomorphism: return f <*> return x = return (f x)
  • interchange: tf <*> return x = return (fun f -> f x) <*> tf

Note: <*> is the infix notation for apply.

val map : [ `Define_using_apply | `Custom of 'a t -> f:('a -> 'b) -> 'b t ]

The map argument to Applicative.Make says how to implement the applicative's map function. `Define_using_apply means to define map t ~f = return f <*> t. `Custom overrides the default implementation, presumably with something more efficient.

Some other functions returned by Applicative.Make are defined in terms of map, so passing in a more efficient map will improve their efficiency as well.

val select : ('a, 'b) Base.Either.t t -> ('a -> 'b) t -> 'b t

Selective applicative functors. You can think of select as a selective function application: you apply a function only when given a value First a. Otherwise, you can skip the function and associted effects and return the b from Second b.

Note that it is not a requirement for selective functors to skip unnecessary effects. It may be counterintuitive, but this makes them more useful. Why? Typically, when executing a selective computation, you would want to skip the effects (saving work); but on the other hand, if your goal is to statically analyse a given selective computation and extract the set of all possible effects (without actually executing them), then you do not want to skip any effects, because that defeats the purpose of static analysis.

The type signature of select is reminiscent of both <*> and >>=, and indeed a selective functor is in some sense a composition of an applicative functor and the Either monad.