package tezos-lwt-result-stdlib

  1. Overview
  2. Docs
Legend:
Library
Module
Module type
Parameter
Class
Class type

Flat is a trace implementation where a trace carries a flat collection of errors. No error is discarded, but the structure (parallel vs sequential) is.

include S
type 'error trace

trace are the errors as received from the monad. In other words, trace is the type of values that are seen when matching on Error _ to, say, recover.

The types 'error and 'error trace are kept separate (although they can be equal) to support cases such as the following:

  • trace are richer than error, such as by including a timestamp, a filename, or some other such metadata.
  • trace is a private type or an abstract type and error is the type of argument to the functions that construct the private/abstract trace.
  • trace is a collection of error and additional functions (not required by this library) allow additional manipulation. E.g., in the case of Tezos: errors are built into traces that can be grown.

There is some leeway about what traces are, what information they carry, etc. Beyond this leeway, Lwtreslib is opinionated about traces. Specifically, Lwtreslib has a notion of sequential and parallel composition. A trace can be either of the following.

  • A single-error trace, i.e., the simplest possible trace that corresponds to a simple failure/issue/unexpected behaviour in the program. See make.
  • A sequential trace, i.e., a trace of errors where one precedes another. This is used to contextualise failures. E.g., in a high-level network handshaking function, a low-level I/O error may be built into a trace that shows how the low-level error caused a high-level issue). See cons.
  • A parallel trace, i.e., a trace of errors that happened in concurrent (or non-causally related) parts of the program. See conp.
val make : 'error -> 'error trace

make e is a trace made of one single error.

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

cons e t is a trace made of the error e composed sequentially with the trace t.

Typically, this is used to give context to a low-level error.

let query key =
  let open Lwt_result_syntax in
  let* c = connect_to_server () in
  let* r = send_query_over_connection c key in
  let* () = check_response r in
  return r

let query key =
  let open Lwt_syntax in
  let+ r = query_key in
  match r with
  | Ok r -> Ok r
  | Error trace -> Error (cons `Query_failure trace)
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 a_bunch_of_errors with
| [] -> Ok () (* or something else depending on the context *)
| error :: errors -> Error (cons_list error errors)
val conp : 'error trace -> 'error trace -> 'error trace

conp t1 t2 is a trace made of the traces t1 and t2 composed concurrently.

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 a_bunch_of_traces with
| [] -> Ok () (* or something else depending on the context *)
| trace :: traces -> Error (conp_list trace traces)

Note that the Lwtreslib's library does not require it, but it is recommended that you also make, for your own use, a pretty-printing function as well as some introspection functions.

One possible extension can be found in examples/traces/traces.ml.

val pp : (Format.formatter -> 'err -> unit) -> Format.formatter -> 'err trace -> unit
val pp_top : (Format.formatter -> 'err -> unit) -> Format.formatter -> 'err trace -> unit
val fold : ('a -> 'error -> 'a) -> 'a -> 'error trace -> 'a
val salvage : ('error -> 'a option) -> 'error trace -> ('a, 'error trace) result
val salvage_s : ('error -> 'a Lwt.t option) -> 'error trace -> ('a, 'error trace) result Lwt.t
val salvage_e : ('error -> ('a, 'error trace) result option) -> 'error trace -> ('a, 'error trace) result
val salvage_es : ('error -> ('a, 'error trace) result Lwt.t option) -> 'error trace -> ('a, 'error trace) result Lwt.t
val recover : ('error -> 'a option) -> ('error trace -> 'a) -> 'error trace -> 'a
val recover_s : ('error -> 'a Lwt.t option) -> ('error trace -> 'a Lwt.t) -> 'error trace -> 'a Lwt.t
val recover_e : ('error -> ('a, 'error trace) result option) -> ('error trace -> ('a, 'error trace) result) -> 'error trace -> ('a, 'error trace) result
val recover_es : ('error -> ('a, 'error trace) result Lwt.t option) -> ('error trace -> ('a, 'error trace) result Lwt.t) -> 'error trace -> ('a, 'error trace) result Lwt.t
val wrap : ('a -> 'b) -> 'a trace -> 'b trace