Module Rresult

Result value combinators.

Rresult is a module for handling computation results and errors in an explicit and declarative manner without resorting to exceptions. It defines a result type equal to OCaml 4.03's result type and combinators to operate on these values.

Open the module to use it, this defines the result type, the R.Infix operators R in your scope.

Consult usage guidelines for the type.

v0.5.0 - homepage


type ('a, 'b) result = ('a'bResult.result =
| Ok of 'a
| Error of 'b

The type for results.

val (>>=) : ('a'bResult.result -> ('a -> ('c'bResult.result) -> ('c'bResult.result

(>>=) is R.( >>= ).

val (>>|) : ('a'bResult.result -> ('a -> 'c) -> ('c'bResult.result

(>>|) is R.( >>| ).

module R : sig ... end

Result value combinators.

Usage design guidelines

These are rough design guidelines, don't forget to think.

Error messages

Use error messages if:

  1. Your error messages don't need to be localized, e.g. scripts, command line programs.
  2. The errors don't need to be processed. They are just meant to be logged at certain point in your program.

If the above doesn't hold and your errors need to be processed for localization or error recovery then use a custom error type in your result values.

Custom error types

If your module has specific errors then define an error type, and a result type that tags this error type with the library name (or any other tag that may make sense, see for example R:exn) along with the following functions:

module Mod : sig
  type error = ...
  type 'a result = ('a, [`Mod of error]) Rresult.result
  val pp_error : Format.formatter -> [`Mod of error] -> unit
  val open_error : 'a result -> ('a, [> `Mod of error]) Rresult.result
  val error_to_msg : 'a result -> ('a, Rresult.R.msg) Rresult.result

  val f : ... -> 'a result

If your library has generic errors that may be useful in other context or shared among modules and to be composed together, then define your error type itself as being a variant and return these values without tagging them.

module Mod : sig
  type error = [`Generic of ... | ... ]
  type 'a result = ('a, error) Rresult.result
  val pp_error : Format.formatter -> error -> unit
  val open_error : 'a result -> ('a, [> error]) Rresult.result
  val error_to_msg : 'a result -> ('a, Rresult.R.msg) Rresult.result

  val f : ... -> 'a result

In the latter case it may still be useful to provide a function to tag these errors whenever they reach a certain point of the program. For this the following function could be added to Mod:

val pack_error : 'a result ->  ('a, [> `Mod of error]) Rresult.result

You should then provide the following functions aswell, so that the packed error composes well in the system:

val pp_pack_error : Format.formatter -> [ `Mod of error] -> unit
val open_pack_error :  ('a, [ `Mod of error]) Rresult.result ->
  ('a, [> `Mod of error]) Rresult.result

val error_pack_to_msg : ('a, [ `Mod of error]) Rresult.result ->
  ('a, Rresult.R.msg) Rresult.result