PVEM actually stands for “Polymorphic Variants-based Error Monads.”
The basic idea of these modules is to manipulate:
type ('ok, 'error) result = [ | `Ok of 'ok | `Error of 'error ]
or combinations of that type (why polymorphic variants? see some implementation notes).
When you open Pvem
(or include
) in your source, you get
Result
which implements the interface ERROR_MONAD
with the above type,With_deferred
: DEFERRED
→ DEFERRED_RESULT
which
builds “error-monads” out of `Lwt`-like
concurrency monads.Since the monad(s) become pervasive; the
ERROR_MONAD
module type defines 3 infix operators:
>>=
(ERROR_MONAD.bind
): the “standard” bind operator.>>|
(ERROR_MONAD.map
): pass the value through a “pure” function.>><
(ERROR_MONAD.destruct
): “reopen” the error monad to be able to match
on both the “Ok” and “Error” cases; then return inside the monad like with
bind
.Here is a basic usage example for the 3 infix operators:
open Pvem open Result let fail_on_42 : int -> (int, string) Result.t = function 42 -> fail "42" | other -> return other let f_uses_bind_and_return: int -> (float, string) Result.t = fun x -> fail_on_42 x >>= fun not_42 -> return (2. *. float not_42) let f_uses_map: int -> (int * int, string) Result.t = fun x -> fail_on_42 x >>| (fun x -> (x, x)) let f_uses_destruct: int -> (float, string * string) Result.t = fun x -> fail_on_42 x >>< function | `Ok o -> return (float o) | `Error s -> fail ("did not convert to float", s)
To get an error monad on top of Lwt, simply
module Deferred_result = Pvem.With_deferred(Lwt)
With Jane Street's Async Deferred.t
:
open Core_kernel.Std open Async.Std module Deferred_result = Pvem.With_deferred(struct include Deferred let catch tri wiz = Async.Std.try_with tri >>= function | Ok o -> return o | Error e -> wiz e end)