List
defines applications that work across all possible combinations of the items in the respective lists. This is often used to model non-determinism.
E.g., to get all pairs that can be formed by selecting first and second elements from the respective lists:
# let x = List.NonDet.((fun x y -> (x, y)) <@> [1;2] <*> ['a';'b']);;
- : (int * char) list = [(1, 'a'); (1, 'b'); (2, 'a'); (2, 'b')]
include Seed with type 'a t = 'a List.t
include Functor.S with type 'a t = 'a List.t
include Functor.Seed with type 'a t = 'a List.t
The principle type.
The type constructor t
is the mapping of objects taking every type 'a
to a type 'a t
.
val map : f :('a -> 'b ) -> 'a t -> 'b t
map ~f
maps the function f : 'a -> 'b
to a function 'f T : 'a T -> 'b T
.
As an example, if T (x : u) : u t
then map ~(f:u -> v) (T x)
is T (f
x) : v t
. As a result, map
is often thought of as applying f
"in" T
.
The function map
is the mapping of arrows, taking every arrow 'a -> 'b
to an arrow 'a t -> 'b t
.
val (<@>) : ('a -> 'b ) -> 'a t -> 'b t
val (|>>) : 'a t -> ('a -> 'b ) -> 'b t
Mapped version of |>
(which is flipped (<&>)
)
return x
is the minimal value of x
in t
val apply : ('a -> 'b ) t -> 'a t -> 'b t
apply (F f) (F x)
is F (f x)
, i.e., f
applied to x
in t
val map2 : 'a t -> 'b t -> f :('a -> 'b -> 'c ) -> 'c t
map2 ~f x y
is return f <*> x <*> y
, i.e., f
"lifted" in to t
and then applied to both x
and y
.
val (<*>) : ('a -> 'b ) t -> 'a t -> 'b t
(F f) <*> (F x)
is F (f x)
val (*>) : 'a t -> 'b t -> 'b t
a *> b
sequences actions a
and b
but discards the value of a
val (<*) : 'a t -> 'b t -> 'a t
a <* b
sequences actions a
and b
but discards the value of b
val both : 'a t -> 'b t -> ('a * 'b ) t
both (F a) (F b)
is F (a, b)
, i.e., it is the product of a
and b
in F