package ocaml-monadic
Install
dune-project
Dependency
Authors
Maintainers
Sources
md5=97a13f2bd6f914db1255765cf7ec2769
sha512=03d828166512c52323186ad40d4b3bcd0d171aab6871e3ca4ad652f195eb01384c48ff8efa551eb1837bd3d1835f5e97a61f592d7b2a265466bae196b0502e2e
doc/README.html
ocaml-monadic
Lightweight PPX extension for OCaml to support natural monadic syntax.
Purpose
At the time of this writing, the PPX syntax extensions for monads available in the OPAM repositories are largely invested in providing a monadic syntax which looks similar to that of Haskell. While this syntax is familiar, it is also quite different from OCaml's syntax (and even from Haskell's non-monadic syntax), leading to a well-known difficulty in transitioning existing code to and from monadic form. This syntax extension aims to provide a monadic syntax which blends more readily with that of OCaml.
Extensions
let%bind, if%bind, match%bind, ;%bind
The first syntax extension provided by this library is the %bind syntax.
let%bind is supported only for non-recursive let expressions. For instance, the code
let%bind x = [1;2;3] in
let%bind y = [4;5;6] in
return (x + y)desugars to
bind [1;2;3] (fun x ->
bind [4;5;6] (fun y ->
return (x+y)
)
)if%bind permits monadic values to be used directly in conditions. The code
if%bind x then
return a
else
return bdesugars to
bind x (function
| true -> return a
| false -> return b
)match%bind permits monadic values to be used as match subjects; the code
match%bind x with
| A -> return a
| B -> return bdesugars to
bind x (function
| A -> return a
| B -> return b
);%bind allows monadic unit expressions to be sequenced directly. The code
expr1 ;%bind
expr2 ;%bind
return ()desugars to
bind expr1 (fun () ->
bind expr2 (fun () ->
return ()
)
)In all of the above cases, the function bind is assumed to be defined in local scope; this may occur in any fashion but is most easily accomplished with a local open (e.g. let open MyMonad in).
let%orzero
The let%orzero extension, which also applies only to non-recursive let expressions, is used with monads that are equipped with a zero operation (such as monads for nondeterminism or exception handling). It allows the refutable destruction of a value; refutations become zeroed. For instance, the code
let%orzero Foo(a,b) = x in
return (a + b)desugars to
match x with
| Foo(a,b) -> return (a + b)
| _ -> zero ()The function zero is assumed to be bound in local scope.
Although the above is handy when dealing with zero-equipped monads, non-zero monads can be given ad-hoc orzero behavior by binding a zero function. For instance, one might consider the following code:
let some_fn x =
let open StateMonad in
let zero () = raise (Invariant_exception "state value has wrong form") in
let%orzero Foo(a) = get () in
set (Foo(a+x));
return (a+x)
;;In the above, let%orzero is used to destruct a value provided by a state monad. Although the state monad is not equipped with a zero operation, a local definition of zero is provided here to handle the case in which the stateful value does not match the expected form. This is, of course, increasingly beneficial as the number of let%orzero operations increases, as it allows us to amortize the cost of defining the ad-hoc zero.
[%guard]
The [%guard] extension accepts a single expression as its payload and is also used with zero-equipped monads. It is used to stop computation and produce a zero unless a condition holds. For example, the code
[%guard b];
return xdesugars to
if b then return x else zero ()The primary value of [%guard] is that it permits these condition checks in a terse, naturally sequential fashion and in a way which automatic code formatters (such as ocp-indent) will respect. Note that [%guard] is only processed when it appears on the left-hand side of a sequence operator.
Usage
To use the above syntax extensions, it should be sufficient to name the ocaml-monadic package in an invocation of ocamlbuild or ocamlfind. The lib/META file (generated here by lib/META.ab) ensures that ocamlfind will apply the PPX extension. For OASIS users, it should be sufficient to add ocaml-monadic to a library's BuildDepends section in an _oasis file. For dune/jbuilder users simply add ocaml-monadic to the (preprocess (pps (...))) stanza of your jbuild file, like you would with any other ppx.