tezos-error-monad

Tezos: error monad
Library tezos-error-monad

A trace is a stack of errors. It is implemented as an error list but such a list MUST NEVER be empty.

It is implemented as a concrete error list for backwards compatibility but future improvements might modify the type or render the type abstract.

include Sig.TRACE with type 'err trace = 'err list
type 'err trace = 'err list

trace is abstract in this interface but it is made concrete in the instantiated error monad (see error_monad.mli).

The idea of abstracting the trace is so that it can evolve more easily. Eventually, we can make the trace abstract in the instantiated error monad, we can have different notions of traces for the protocol and the shell, etc.

val make : 'error -> 'error trace

make e makes a singleton trace, the simplest of traces that carries a single error.

val cons : 'error -> 'error trace -> 'error trace

cons e t (construct sequential) constructs a sequential trace. This is for tracing events/failures/things that happen one after the other, generally one as a consequence of the other. E.g.,

let file_handle = match attempt_open name with | Ok handle -> Ok handle | Error error -> let trace = make error in match attempt_create name with | Ok handle -> Ok handle | Error error -> Error (cons error trace)

When you are within the error monad itself, you should build traces using the record_trace, trace, record_trace_eval and trace_eval functions directly. You should rarely need to build traces manually using cons. This here function can be useful in the case where you are at the interface of the error monad.

val cons_list : 'error -> 'error list -> 'error trace

cons_list error errors is the sequential composition of all the errors passed as parameters. It is equivalent to folding cons over List.rev error :: errors but more efficient.

Note that error and errors are separated as parameters to enforce that empty traces cannot be constructed. The recommended use is:

match all_errors with
| [] -> Ok () (* or something else depending on the context *)
| error :: errors -> Error (cons_list error errors)

When you are within the error monad itself, you should build traces using the record_trace, trace, record_trace_eval and trace_eval functions directly. You should rarely need to build traces manually using cons_list. This here function can be useful in the case where you are at the interface of the error monad.

val conp : 'error trace -> 'error trace -> 'error trace

conp t1 t2 (construct parallel) construct a parallel trace. This is for tracing events/failure/things that happen concurrently, in parallel, or simply independently of each other. E.g.,

let fetch_density () = let area = fetch_area () in let population = fetch_population () in match area, population with | Ok area, Ok population -> Ok (population / area) | Error trace, Ok _ | Ok _, Error trace -> Error trace | Error trace1, Error trace2 -> Error (conp trace1 trace2)

When you are within the error monad itself, you should rarely need to build traces manually using conp. The result-concurrent traversors will return parallel traces when appropriate, and so will join_e, join_ep, both_e, both_ep, all_e and all_ep.

val conp_list : 'err trace -> 'err trace list -> 'err trace

conp_list trace traces is the parallel composition of all the traces passed as parameters. It is equivalent to List.fold_left conp trace traces but more efficient.

Note that trace and traces are separated as parameters to enforce that empty traces cannot be constructed. The recommended use is:

match all_traces with
| [] -> Ok () (* or something else depending on the context *)
| trace :: traces -> Error (conp_list trace traces)

When you are within the error monad itself, you should rarely need to build traces manually using conp. The result-concurrent traversors will return parallel traces when appropriate, and so will join_e, join_ep, both_e, both_ep, all_e and all_ep.

val pp_print : ( Format.formatter -> 'err -> unit ) -> Format.formatter -> 'err trace -> unit

pp_print pretty-prints a trace of errors

val pp_print_top : ( Format.formatter -> 'err -> unit ) -> Format.formatter -> 'err trace -> unit

pp_print_top pretty-prints the top errors of the trace

val encoding : 'error Data_encoding.t -> 'error trace Data_encoding.t
val fold : ( 'a -> 'error -> 'a ) -> 'a -> 'error trace -> 'a

fold f init trace traverses the trace (in an unspecified manner) so that init is folded over each of the error within trace by f. Typical use is to find the worst error, to check for the presence of a given error, etc.