tezos-error-monad

Tezos: error monad
Library tezos-error-monad
type error_category = [
| `Branch(*

Errors that may not happen in another context

*)
| `Temporary(*

Errors that may not happen in a later context

*)
| `Permanent(*

Errors that will happen no matter the context

*)
]

Categories of error

type error = TzCore.error = ..
include Sig.CORE with type error := error
val error_encoding : error Data_encoding.t
val pp : Format.formatter -> error -> unit
include Sig.EXT with type error := error
val register_error_kind : Sig.error_category -> id:string -> title:string -> description:string -> ?pp:( Format.formatter -> 'err -> unit ) -> 'err Data_encoding.t -> ( error -> 'err option ) -> ( 'err -> error ) -> unit

The error data type is extensible. Each module can register specialized error serializers id unique name of this error. Ex.: overflow_time_counter title more readable name. Ex.: Overflow of time counter description human readable description. Ex.: The time counter overflowed while computing delta increase pp formatter used to pretty print additional arguments. Ex.: The time counter overflowed while computing delta increase. Previous value %d. Delta: %d encoder decoder data encoding for this error. If the error has no value, specify Data_encoding.empty

val register_recursive_error_kind : Sig.error_category -> id:string -> title:string -> description:string -> pp:( Format.formatter -> 'err -> unit ) -> ( error Data_encoding.t -> 'err Data_encoding.t ) -> ( error -> 'err option ) -> ( 'err -> error ) -> unit

Same as register_error_kind but allow errors to wrap other errors.

The encoding argument is a function which will be given the encoding of errors as argument so that you can encode errors in errors using a fixpoint.

Another difference with register_error_kind is that pp is mandatory.

val classify_error : error -> Sig.error_category

Classify an error using the registered kinds

type error +=
| Unclassified of string(*

Catch all error when 'deserializing' an error.

*)

Catch all error when 'serializing' an error.

type error +=
| Unregistered_error of Data_encoding.json
val json_of_error : error -> Data_encoding.json

An error serializer

val error_of_json : Data_encoding.json -> error

Error documentation

type error_info = {
category : Sig.error_category;
id : string;
title : string;
description : string;
schema : Data_encoding.json_schema;
}

Error information

val pp_info : Format.formatter -> error_info -> unit
val get_registered_errors : unit -> error_info list

Retrieves information of registered errors

include Sig.WITH_WRAPPED with type error := error
module type Wrapped_error_monad = sig ... end
val register_wrapped_error_kind : (module Wrapped_error_monad) -> id:string -> title:string -> description:string -> unit
module TzTrace : Sig.TRACE with type 'error trace = 'error list
type 'error trace = 'error TzTrace.trace
include Sig.MONAD with type 'error trace := 'error TzTrace.trace
val ok : 'a -> ( 'a, 'trace ) result

Successful result

val ok_unit : ( unit, 'trace ) result
val ok_none : ( 'a option, 'trace ) result
val ok_some : 'a -> ( 'a option, 'trace ) result
val ok_nil : ( 'a list, 'trace ) result
val ok_true : ( bool, 'trace ) result
val ok_false : ( bool, 'trace ) result
val return : 'a -> ( 'a, 'trace ) result Lwt.t

Successful return

val return_unit : ( unit, 'trace ) result Lwt.t

Successful return of ()

val return_none : ( 'a option, 'trace ) result Lwt.t

Successful return of None

val return_some : 'a -> ( 'a option, 'trace ) result Lwt.t

return_some x is a successful return of Some x

val return_nil : ( 'a list, 'trace ) result Lwt.t

Successful return of []

val return_true : ( bool, 'trace ) result Lwt.t

Successful return of true

val return_false : ( bool, 'trace ) result Lwt.t

Successful return of false

val error : 'err -> ( 'a, 'err TzTrace.trace ) result

Erroneous result

val fail : 'err -> ( 'a, 'err TzTrace.trace ) result Lwt.t

Erroneous return

Infix operators for monadic binds/maps. All operators follow this naming convention:

  • the first character is >
  • the second character is > for bind and | for map
  • the next character is = for Lwt or ? for Error
  • the next character (if present) is = for Lwt or ? for Error, it is only used for operator that are within both monads.
val (>>=) : 'a Lwt.t -> ( 'a -> 'b Lwt.t ) -> 'b Lwt.t

Lwt's bind reexported. Following Lwt's convention, in this operator and the ones below, = indicate we operate within Lwt.

val (>|=) : 'a Lwt.t -> ( 'a -> 'b ) -> 'b Lwt.t

Lwt's map reexported. The | indicates a map rather than a bind.

val (>>?) : ( 'a, 'trace ) result -> ( 'a -> ( 'b, 'trace ) result ) -> ( 'b, 'trace ) result

Non-Lwt bind operator. In this operator and the ones below, ? indicates that we operate within the error monad.

val (>|?) : ( 'a, 'trace ) result -> ( 'a -> 'b ) -> ( 'b, 'trace ) result

Non-Lwt map operator.

val (>>=?) : ( 'a, 'trace ) result Lwt.t -> ( 'a -> ( 'b, 'trace ) result Lwt.t ) -> ( 'b, 'trace ) result Lwt.t

Combined bind operator. The =? indicates that the operator acts within the combined error-lwt monad.

val (>|=?) : ( 'a, 'trace ) result Lwt.t -> ( 'a -> 'b ) -> ( 'b, 'trace ) result Lwt.t

Combined map operator.

val (>>?=) : ( 'a, 'trace ) result -> ( 'a -> ( 'b, 'trace ) result Lwt.t ) -> ( 'b, 'trace ) result Lwt.t

Injecting bind operator. This is for transitioning from the simple Error monad to the combined Error-Lwt monad.

Note the order of the character: it starts with the error monad marker ? and has the Lwt monad marker later. This hints at the role of the operator to transition into Lwt.

val (>|?=) : ( 'a, 'trace ) result -> ( 'a -> 'b Lwt.t ) -> ( 'b, 'trace ) result Lwt.t

Injecting map operator.

val record_trace : 'err -> ( 'a, 'err TzTrace.trace ) result -> ( 'a, 'err TzTrace.trace ) result

Enrich an error report (or do nothing on a successful result) manually

val trace : 'err -> ( 'b, 'err TzTrace.trace ) result Lwt.t -> ( 'b, 'err TzTrace.trace ) result Lwt.t

Automatically enrich error reporting on stack rewind

val record_trace_eval : ( unit -> ( 'err, 'err TzTrace.trace ) result ) -> ( 'a, 'err TzTrace.trace ) result -> ( 'a, 'err TzTrace.trace ) result

Same as record_trace, for unevaluated error

val trace_eval : ( unit -> ( 'err, 'err TzTrace.trace ) result Lwt.t ) -> ( 'b, 'err TzTrace.trace ) result Lwt.t -> ( 'b, 'err TzTrace.trace ) result Lwt.t

Same as trace, for unevaluated Lwt error

val error_unless : bool -> 'err -> ( unit, 'err TzTrace.trace ) result

Error on failed assertion

val error_when : bool -> 'err -> ( unit, 'err TzTrace.trace ) result
val fail_unless : bool -> 'err -> ( unit, 'err TzTrace.trace ) result Lwt.t

Erroneous return on failed assertion

val fail_when : bool -> 'err -> ( unit, 'err TzTrace.trace ) result Lwt.t
val unless : bool -> ( unit -> ( unit, 'trace ) result Lwt.t ) -> ( unit, 'trace ) result Lwt.t
val when_ : bool -> ( unit -> ( unit, 'trace ) result Lwt.t ) -> ( unit, 'trace ) result Lwt.t
val dont_wait : ( exn -> unit ) -> ( 'trace -> unit ) -> ( unit -> ( unit, 'trace ) result Lwt.t ) -> unit

Wrapper around Lwt_utils.dont_wait

val join_p : unit Lwt.t list -> unit Lwt.t

A few aliases for Lwt functions

val all_p : 'a Lwt.t list -> 'a list Lwt.t
val both_p : 'a Lwt.t -> 'b Lwt.t -> ('a * 'b) Lwt.t
val join_e : ( unit, 'err TzTrace.trace ) result list -> ( unit, 'err TzTrace.trace ) result

Similar functions in the error monad

val all_e : ( 'a, 'err TzTrace.trace ) result list -> ( 'a list, 'err TzTrace.trace ) result
val both_e : ( 'a, 'err TzTrace.trace ) result -> ( 'b, 'err TzTrace.trace ) result -> ( 'a * 'b, 'err TzTrace.trace ) result
val join_ep : ( unit, 'err TzTrace.trace ) result Lwt.t list -> ( unit, 'err TzTrace.trace ) result Lwt.t

Similar functions in the combined monad

val all_ep : ( 'a, 'err TzTrace.trace ) result Lwt.t list -> ( 'a list, 'err TzTrace.trace ) result Lwt.t
val both_ep : ( 'a, 'err TzTrace.trace ) result Lwt.t -> ( 'b, 'err TzTrace.trace ) result Lwt.t -> ( 'a * 'b, 'err TzTrace.trace ) result Lwt.t
include Sig.MONAD_EXT with type error := error and type 'error trace := 'error TzTrace.trace
type tztrace = error TzTrace.trace
type 'a tzresult = ( 'a, tztrace ) result
val classify_errors : tztrace -> Sig.error_category
val pp_print_error : Format.formatter -> error TzTrace.trace -> unit
val pp_print_error_first : Format.formatter -> error TzTrace.trace -> unit

Pretty prints a trace as the message of its first error

val trace_encoding : error TzTrace.trace Data_encoding.t
val result_encoding : 'a Data_encoding.t -> 'a tzresult Data_encoding.t

A serializer for result of a given type

val generic_error : ( 'a, Format.formatter, unit, 'b tzresult ) format4 -> 'a

Erroneous result (shortcut for generic errors)

val failwith : ( 'a, Format.formatter, unit, 'b tzresult Lwt.t ) format4 -> 'a

Erroneous return (shortcut for generic errors)

val error_exn : exn -> 'a tzresult
val record_trace_exn : exn -> 'a tzresult -> 'a tzresult
val trace_exn : exn -> 'b tzresult Lwt.t -> 'b tzresult Lwt.t
val generic_trace : ( 'a, Format.formatter, unit, ( 'b, error trace ) result Lwt.t -> ( 'b, error trace ) result Lwt.t ) format4 -> 'a
val pp_exn : Format.formatter -> exn -> unit
val failure : ( 'a, Format.formatter, unit, error ) format4 -> 'a
type error +=
| Exn of exn

Wrapped OCaml/Lwt exception

type error +=
| Canceled
val protect : ?on_error:( error trace -> 'a tzresult Lwt.t ) -> ?canceler:Lwt_canceler.t -> ( unit -> 'a tzresult Lwt.t ) -> 'a tzresult Lwt.t

protect is a wrapper around Lwt.catch where the error handler operates over `trace` instead of `exn`. Besides, protect ~on_error ~canceler ~f may *cancel* f via a Lwt_canceler.t.

More precisely, protect ~on_error ~canceler f runs f (). An Lwt failure triggered by f () is wrapped into an Exn. If a canceler is given and Lwt_canceler.cancellation canceler is determined before f (), a Canceled error is returned.

Errors are caught by ~on_error (if given), otherwise the previous value is returned. An Lwt failure triggered by ~on_error is wrapped into an Exn

type error +=
| Timeout
val with_timeout : ?canceler:Lwt_canceler.t -> unit Lwt.t -> ( Lwt_canceler.t -> 'a tzresult Lwt.t ) -> 'a tzresult Lwt.t