Pvem: Home

Play with Error-Monads in OCaml

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

  • the module Result which implements the interface ERROR_MONAD with the above type,
  • the functor With_deferred: DEFERREDDEFERRED_RESULT which builds “error-monads” out of `Lwt`-like concurrency monads.

Examples

Here is some basic usage of >>= (bind), >>| (map), and >>< (destruct) (see also the ERROR_MONAD module type):

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)

Alternatives

The following libraries use “normal” variants and hence are incompatible from each other: