Page
Library
Module
Module type
Parameter
Class
Class type
Source
ReaSourceWARNING: Many of the combinators are documented concisely in the format "X is equivalent to Y". The equivalence should only be assumed to hold modulo more or less obvious OCaml evaluation order differences.
Success type abbreviation.
Failure type abbreviation.
Choice type abbrevation.
Continuation passing style function type abbreviation.
Unary operation type abbreviation.
Binary operation type abbreviation.
Lazy binary operation type abbrevation.
The effect framework in this section is almost entirely free of concrete implementation details and should theoretically be usable in a wide variety of contexts including for wrapping existing monadic libraries.
The effect framework can also be extended by users. Consider the map effect. It consists of
map'm effect signature type abbreviation,map' capability mix-in,map combinator, andmonad'd.And, of course, various interpreters implement the map' capability. The bottom line is that nothing prevents user defined extensions following the same pattern.
Empty variant type used to ensure that no errors can be left unhandled.
Abstract effect signature represents the application ('e, 'a) 'R of the higher-kinded effect representation type constructor 'R to the error 'e and answer 'a types.
Basic use of this framework should rarely require one to refer to this type, but this type will appear in inferred types. When writing type signatures the effect reader type abbreviation er should be preferred.
Effect reader takes a dictionary 'D of capabilities and returns an effect with the signature ('R, 'e, 'a) s.
Effect readers are functions that take a dictionary of capabilities. This allows a form of laziness via η-expansion and effect signatures are designed to allow implementations to delay invoking the effect reader functions until the effects are really needed.
eta'0 @@ fun () -> f is equivalent to fun d -> f d.
Consider the following fib implementation:
let rec fib n = eta'0 @@ fun () ->
if n <= 1 then
pure n
else
lift'2 (+) (fib (n - 2)) (fib (n - 1))The eta'0 @@ fun () -> ... makes it so that fib n returns in O(1) time without building the complete computation tree.
eta'1 @@ fun x -> f is equivalent to fun x d -> f x d.
Consider the following list traversal implementation:
let rec map_er xyE = eta'1 @@ function
| [] -> pure []
| x :: xs ->
let+ y = xyE x
and+ ys = map_er xyE xs in
y :: ysThe eta'1 @@ function ... makes it so that map_er xyE xs returns in O(1) time without going through the whole list to compute a complete computation tree for it.
TODO
run d xE is equivalent to xE d.
map effect signature.
map xy xE effect.
( let+ ) xE xy is equivalent to map xy xE.
xE >>- xy is equivalent to map xy xE.
val (>->) :
('a -> ('R, 'e, 'b, ['R, 'D] map' as 'D) er) ->
('b -> 'c) ->
'a ->
('R, 'e, 'c, 'D) erxyE >-> yz is equivalent to fun x -> map yz (xyE x).
lift'1 xy xE is equivalent to map xy xE.
return value is equivalent to pure value.
do_unless b uE is equivalent to if b then unit else uE.
do_when b uE is equivalent to if b then uE else unit.
type ('R, 'e, 'a, 'b, 'D) pair'm =
('R, 'e, 'a, 'D) er ->
('R, 'e, 'b, 'D) er ->
('R, 'e, 'a * 'b) spair effect signature.
val pair :
('R, 'e, 'a, ['R, 'D] pair' as 'D) er ->
('R, 'e, 'b, 'D) er ->
('R, 'e, 'a * 'b, 'D) erpair xE yE effect.
val (and+) :
('R, 'e, 'a, ['R, 'D] pair' as 'D) er ->
('R, 'e, 'b, 'D) er ->
('R, 'e, 'a * 'b, 'D) er( and+ ) xE yE is equivalent to pair xE yE.
val (<*>) :
('R, 'e, 'a, ['R, 'D] pair' as 'D) er ->
('R, 'e, 'b, 'D) er ->
('R, 'e, 'a * 'b, 'D) erxE <*> yE is equivalent to pair xE yE.
val tuple'2 :
('R, 'e, 'a, ['R, 'D] pair' as 'D) er ->
('R, 'e, 'b, 'D) er ->
('R, 'e, 'a * 'b, 'D) ertuple'2 x1E x2E is equivalent to pair x1E x2E.
val tuple'3 :
('R, 'e, 'a1, ['R, 'D] product' as 'D) er ->
('R, 'e, 'a2, 'D) er ->
('R, 'e, 'a3, 'D) er ->
('R, 'e, 'a1 * 'a2 * 'a3, 'D) ertuple'3 x1E x2E x3E is equivalent to map (fun (x1, (x2, x3)) -> (x1, x2, x3)) (pair x1E (pair x2E x3E)).
val tuple'4 :
('R, 'e, 'a1, ['R, 'D] product' as 'D) er ->
('R, 'e, 'a2, 'D) er ->
('R, 'e, 'a3, 'D) er ->
('R, 'e, 'a4, 'D) er ->
('R, 'e, 'a1 * 'a2 * 'a3 * 'a4, 'D) ertuple'4 x1E x2E x3E x4E is like tuple'3, but for 4 elements.
val tuple'5 :
('R, 'e, 'a1, ['R, 'D] product' as 'D) er ->
('R, 'e, 'a2, 'D) er ->
('R, 'e, 'a3, 'D) er ->
('R, 'e, 'a4, 'D) er ->
('R, 'e, 'a5, 'D) er ->
('R, 'e, 'a1 * 'a2 * 'a3 * 'a4 * 'a5, 'D) ertuple'5 x1E x2E x3E x4E x5E is like tuple'3, but for 5 elements.
val tuple'6 :
('R, 'e, 'a1, ['R, 'D] product' as 'D) er ->
('R, 'e, 'a2, 'D) er ->
('R, 'e, 'a3, 'D) er ->
('R, 'e, 'a4, 'D) er ->
('R, 'e, 'a5, 'D) er ->
('R, 'e, 'a6, 'D) er ->
('R, 'e, 'a1 * 'a2 * 'a3 * 'a4 * 'a5 * 'a6, 'D) ertuple'6 x1E x2E x3E x4E x5E x6E is like tuple'3, but for 6 elements.
TODO
val map_er'2 :
('b1 -> ('R, 'e, 'a1, ['R, 'D] product' as 'D) er) ->
('b2 -> ('R, 'e, 'a2, 'D) er) ->
('b1 * 'b2) ->
('R, 'e, 'a1 * 'a2, 'D) erTODO
val map_er'3 :
('b1 -> ('R, 'e, 'a1, ['R, 'D] product' as 'D) er) ->
('b2 -> ('R, 'e, 'a2, 'D) er) ->
('b3 -> ('R, 'e, 'a3, 'D) er) ->
('b1 * 'b2 * 'b3) ->
('R, 'e, 'a1 * 'a2 * 'a3, 'D) erTODO
val map_er'4 :
('b1 -> ('R, 'e, 'a1, ['R, 'D] product' as 'D) er) ->
('b2 -> ('R, 'e, 'a2, 'D) er) ->
('b3 -> ('R, 'e, 'a3, 'D) er) ->
('b4 -> ('R, 'e, 'a4, 'D) er) ->
('b1 * 'b2 * 'b3 * 'b4) ->
('R, 'e, 'a1 * 'a2 * 'a3 * 'a4, 'D) erTODO
val map_er'5 :
('b1 -> ('R, 'e, 'a1, ['R, 'D] product' as 'D) er) ->
('b2 -> ('R, 'e, 'a2, 'D) er) ->
('b3 -> ('R, 'e, 'a3, 'D) er) ->
('b4 -> ('R, 'e, 'a4, 'D) er) ->
('b5 -> ('R, 'e, 'a5, 'D) er) ->
('b1 * 'b2 * 'b3 * 'b4 * 'b5) ->
('R, 'e, 'a1 * 'a2 * 'a3 * 'a4 * 'a5, 'D) erTODO
val map_er'6 :
('b1 -> ('R, 'e, 'a1, ['R, 'D] product' as 'D) er) ->
('b2 -> ('R, 'e, 'a2, 'D) er) ->
('b3 -> ('R, 'e, 'a3, 'D) er) ->
('b4 -> ('R, 'e, 'a4, 'D) er) ->
('b5 -> ('R, 'e, 'a5, 'D) er) ->
('b6 -> ('R, 'e, 'a6, 'D) er) ->
('b1 * 'b2 * 'b3 * 'b4 * 'b5 * 'b6) ->
('R, 'e, 'a1 * 'a2 * 'a3 * 'a4 * 'a5 * 'a6, 'D) erTODO
TODO
val map_eq_er'2 :
('a1 -> ('R, 'e, 'a1, ['R, 'D] product' as 'D) er) ->
('a2 -> ('R, 'e, 'a2, 'D) er) ->
('a1 * 'a2) ->
('R, 'e, 'a1 * 'a2, 'D) erTODO
val map_eq_er'3 :
('a1 -> ('R, 'e, 'a1, ['R, 'D] product' as 'D) er) ->
('a2 -> ('R, 'e, 'a2, 'D) er) ->
('a3 -> ('R, 'e, 'a3, 'D) er) ->
('a1 * 'a2 * 'a3) ->
('R, 'e, 'a1 * 'a2 * 'a3, 'D) erTODO
val map_eq_er'4 :
('a1 -> ('R, 'e, 'a1, ['R, 'D] product' as 'D) er) ->
('a2 -> ('R, 'e, 'a2, 'D) er) ->
('a3 -> ('R, 'e, 'a3, 'D) er) ->
('a4 -> ('R, 'e, 'a4, 'D) er) ->
('a1 * 'a2 * 'a3 * 'a4) ->
('R, 'e, 'a1 * 'a2 * 'a3 * 'a4, 'D) erTODO
val map_eq_er'5 :
('a1 -> ('R, 'e, 'a1, ['R, 'D] product' as 'D) er) ->
('a2 -> ('R, 'e, 'a2, 'D) er) ->
('a3 -> ('R, 'e, 'a3, 'D) er) ->
('a4 -> ('R, 'e, 'a4, 'D) er) ->
('a5 -> ('R, 'e, 'a5, 'D) er) ->
('a1 * 'a2 * 'a3 * 'a4 * 'a5) ->
('R, 'e, 'a1 * 'a2 * 'a3 * 'a4 * 'a5, 'D) erTODO
val map_eq_er'6 :
('a1 -> ('R, 'e, 'a1, ['R, 'D] product' as 'D) er) ->
('a2 -> ('R, 'e, 'a2, 'D) er) ->
('a3 -> ('R, 'e, 'a3, 'D) er) ->
('a4 -> ('R, 'e, 'a4, 'D) er) ->
('a5 -> ('R, 'e, 'a5, 'D) er) ->
('a6 -> ('R, 'e, 'a6, 'D) er) ->
('a1 * 'a2 * 'a3 * 'a4 * 'a5 * 'a6) ->
('R, 'e, 'a1 * 'a2 * 'a3 * 'a4 * 'a5 * 'a6, 'D) erTODO
val lift'2 :
('b1 -> 'b2 -> 'a) ->
('R, 'e, 'b1, ['R, 'D] product' as 'D) er ->
('R, 'e, 'b2, 'D) er ->
('R, 'e, 'a, 'D) erlift'2 xyz xE yE is equivalent to map (fun (x, y) -> xyz x y) (pair xE yE).
val lift'3 :
('b1 -> 'b2 -> 'b3 -> 'a) ->
('R, 'e, 'b1, ['R, 'D] product' as 'D) er ->
('R, 'e, 'b2, 'D) er ->
('R, 'e, 'b3, 'D) er ->
('R, 'e, 'a, 'D) erTODO
val lift'4 :
('b1 -> 'b2 -> 'b3 -> 'b4 -> 'a) ->
('R, 'e, 'b1, ['R, 'D] product' as 'D) er ->
('R, 'e, 'b2, 'D) er ->
('R, 'e, 'b3, 'D) er ->
('R, 'e, 'b4, 'D) er ->
('R, 'e, 'a, 'D) erTODO
val lift'5 :
('b1 -> 'b2 -> 'b3 -> 'b4 -> 'b5 -> 'a) ->
('R, 'e, 'b1, ['R, 'D] product' as 'D) er ->
('R, 'e, 'b2, 'D) er ->
('R, 'e, 'b3, 'D) er ->
('R, 'e, 'b4, 'D) er ->
('R, 'e, 'b5, 'D) er ->
('R, 'e, 'a, 'D) erTODO
val lift'6 :
('b1 -> 'b2 -> 'b3 -> 'b4 -> 'b5 -> 'b6 -> 'a) ->
('R, 'e, 'b1, ['R, 'D] product' as 'D) er ->
('R, 'e, 'b2, 'D) er ->
('R, 'e, 'b3, 'D) er ->
('R, 'e, 'b4, 'D) er ->
('R, 'e, 'b5, 'D) er ->
('R, 'e, 'b6, 'D) er ->
('R, 'e, 'a, 'D) erTODO
type ('R, 'e, 'a, 'b, 'c, 'D) branch'm =
('R, 'e, 'b -> 'a, 'D) er ->
('R, 'e, 'c -> 'a, 'D) er ->
('R, 'e, ('b, 'c) branch, 'D) er ->
('R, 'e, 'a) sbranch effect signature.
val branch :
('R, 'e, 'b -> 'a, 'D) er ->
('R, 'e, 'c -> 'a, 'D) er ->
('R, 'e, ('b, 'c) branch, ['R, 'D] branch' as 'D) er ->
('R, 'e, 'a, 'D) erbranch baE caE bcE effect.
val if_else_s :
('R, 'e, 'a, 'D) er ->
('R, 'e, 'a, 'D) er ->
('R, 'e, bool, ['R, 'D] selective' as 'D) er ->
('R, 'e, 'a, 'D) erif_else_s tE eE cE is equivalent to
branch
(map const eE)
(map const tE)
(map (function true -> Left ()
| false -> Right ())
cE) type ('R, 'e, 'a, 'b, 'D) bind'm =
('R, 'e, 'b, 'D) er ->
('b -> ('R, 'e, 'a, 'D) er) ->
('R, 'e, 'a) sbind effect signature.
val bind :
('R, 'e, 'b, ['R, 'D] bind' as 'D) er ->
('b -> ('R, 'e, 'a, 'D) er) ->
('R, 'e, 'a, 'D) erbind xE xyE effect.
val (>>=) :
('R, 'e, 'b, ['R, 'D] bind' as 'D) er ->
('b -> ('R, 'e, 'a, 'D) er) ->
('R, 'e, 'a, 'D) erxE >>= xyE is equivalent to bind xE xyE.
val (let*) :
('R, 'e, 'b, ['R, 'D] bind' as 'D) er ->
('b -> ('R, 'e, 'a, 'D) er) ->
('R, 'e, 'a, 'D) er( let* ) xE xyE is equivalent to bind xyE xE.
val (and*) :
('R, 'e, 'a, ['R, 'D] pair' as 'D) er ->
('R, 'e, 'b, 'D) er ->
('R, 'e, 'a * 'b, 'D) er( and* ) xE yE is equivalent to pair xE yE.
join xEE is equivalent to bind xEE (fun xE -> xE).
uE >> xE is equivalent to bind uE (fun () -> xE).
val (>=>) :
('a -> ('R, 'e, 'b, ['R, 'D] bind' as 'D) er) ->
('b -> ('R, 'e, 'c, 'D) er) ->
'a ->
('R, 'e, 'c, 'D) erxyE >=> yzE is equivalent to fun x -> bind (xyE x) yzE.
lE &&& rE is equivalent to bind lE (function true -> pure true | false -> rE).
lE &&& rE is equivalent to bind lE (function true -> rE | false -> pure true).
alt effect signature.
val filter :
('a -> bool) ->
('R, 'e, 'a, < ('R, 'D) monad' ; ('R, 'D) zero'.. > as 'D) er ->
('R, 'e, 'a, 'D) erTODO
type ('R, 'e, 'f, 'a, 'b, 'D) tryin'm =
('f -> ('R, 'e, 'a, 'D) er) ->
('b -> ('R, 'e, 'a, 'D) er) ->
('R, 'f, 'b, 'D) er ->
('R, 'e, 'a) stryin effect signature.
val tryin :
('f -> ('R, 'e, 'a, ['R, 'D] tryin' as 'D) er) ->
('b -> ('R, 'e, 'a, 'D) er) ->
('R, 'f, 'b, 'D) er ->
('R, 'e, 'a, 'D) ertryin exE yxE xE effect.
val catch :
('R, 'e, 'a, < ('R, 'D) pure' ; ('R, 'D) tryin'.. > as 'D) er ->
('R, 'f, ('e, 'a) res, 'D) ercatch xE is equivalent to tryIn (fun e -> pure (`Error e)) (fun x -> pure (`Ok x)) xE.
val handle :
('f -> ('R, 'e, 'a, < ('R, 'D) pure' ; ('R, 'D) tryin'.. > as 'D) er) ->
('R, 'f, 'a, 'D) er ->
('R, 'e, 'a, 'D) erhandle exE xE is equivalent to tryin exE pure xE
val finally :
('R, 'e, unit, < ('R, 'D) monad' ; ('R, 'D) errors'.. > as 'D) er ->
('R, 'e, 'a, 'D) er op'1finally uE xE is equivalent to tryin (fun e -> bind uE (fun () -> fail e)) (fun x -> bind uE (fun () -> pure x)) xE.
val map_error :
('f -> 'e) ->
('R, 'f, 'a, < ('R, 'D) pure' ; ('R, 'D) errors'.. > as 'D) er ->
('R, 'e, 'a, 'D) erTODO
val gen_error :
('R, nothing, 'a, < ('R, 'D) pure' ; ('R, 'D) errors'.. > as 'D) er ->
('R, 'e, 'a, 'D) erTODO
val par :
('R, 'e, 'a, ['R, 'D] par' as 'D) er ->
('R, 'e, 'b, 'D) er ->
('R, 'e, 'a * 'b, 'D) erpar xE yE effect.
suspend effect signature.
suspend with_resume effect.
spawn effect signature.
spawn uE effect.
The environment or reader is built-in to the effect system in the form of the capability dictionary. Thanks to OCaml's structural objects, it is possible to extend the dictionary for user needs.
env effect returns the dictionary 'd of capabilities.
env_as fn effect returns the value of type 'a computed from the dictionary of capabilities of type 'd.
mapping_env fn er effect executes the effect er with the dictionary of capabilities of type 'D mapped through the given function fn.
setting_env s er effect executes the effect er with the given dictionary s of capabilities.
An abstraction for accessing instance variables or properties of objects.
prop get set is equivalent to Prop.make get set.
get prop_of effect returns the value of the property from the dictionary of capabilities of type 'd.
get_as prop_of fn
mapping prop_of fn xE effect executes the effect xE with the property of the dictionary of capabilities mapped through the given function.
setting prop_of value xE effect executess the effect xE with the property of the dictionary of capabilities set to given value.
val read :
('D -> 'v Mut.t Prop.t) ->
('R, 'e, 'v, < ('R, 'D) monad' ; ('R, 'D) suspend'.. > as 'D) erread prop_of effect.
val mutate :
('D -> 'v Mut.t Prop.t) ->
'v op'1 ->
('R, 'e, unit, < ('R, 'D) monad' ; ('R, 'D) suspend'.. > as 'D) ermutate prop_of vv effect.
val modify :
('D -> 'v Mut.t Prop.t) ->
('v -> 'v * 'a) ->
('R, 'e, 'a, < ('R, 'D) monad' ; ('R, 'D) suspend'.. > as 'D) ermodify prop_of vva effect.
val try_mutate :
('D -> 'v Mut.t Prop.t) ->
('v -> ('R, 'e, 'v, 'D) er) ->
('R,
'e,
unit,
< ('R, 'D) monad'
; ('R, 'D) errors'
; ('R, 'D) suspend'.. > as 'D)
ertry_mutate prop_of vvE effect.
val try_modify :
('D -> 'v Mut.t Prop.t) ->
('v -> ('R, 'e, 'v * 'a, 'D) er) ->
('R,
'e,
'a,
< ('R, 'D) monad'
; ('R, 'D) errors'
; ('R, 'D) suspend'.. > as 'D)
ertry_modify prop_of vvaE effect.
val cloning :
('D -> 'v Mut.t Prop.t) ->
('R, 'e, 'a, < ('R, 'D) monad' ; ('R, 'D) suspend'.. > as 'D) er op'1cloning prop_of xE effect.
Users can and often should implement their own interpreters that only allow specific limited sets of effects. This package is intended to only provide the core framework for effectul programming.
A self tail recursive interpreter usable with Js_of_ocaml.