Mavryk_error_monad.TzMonad
module Option_syntax = TzLwtreslib.Monad.Option_syntax
module Lwt_option_syntax = TzLwtreslib.Monad.Lwt_option_syntax
include Monad_maker.S
with type error := TzCore.error
and type 'error trace := 'error TzTrace.trace
type tztrace = TzCore.error TzTrace.trace
type 'a tzresult = ('a, tztrace) Stdlib.result
module Lwt_syntax : module type of TzLwtreslib.Monad.Lwt_syntax
module Result_syntax : sig ... end
module Lwt_result_syntax : sig ... end
val classify_trace : tztrace -> Error_classification.t
val pp_print_trace : Stdlib.Format.formatter -> tztrace -> unit
val pp_print_top_error_of_trace : Stdlib.Format.formatter -> tztrace -> unit
Pretty-prints the top error of a trace
val trace_encoding : tztrace Data_encoding.t
val result_encoding : 'a Data_encoding.t -> 'a tzresult Data_encoding.t
A serializer for result of a given type
val record_trace :
'err ->
('a, 'err TzTrace.trace) Stdlib.result ->
('a, 'err TzTrace.trace) Stdlib.result
record_trace err res
is either res
if res
is Ok _
, or it is Error (Trace.cons err tr)
if res
is Error tr
.
In other words, record_trace err res
enriches the trace that is carried by res
(if it is carrying a trace) with the error err
. It leaves res
untouched if res
is not carrying a trace.
You can use this to add high-level information to potential low-level errors. E.g.,
record_trace
Failure_to_load_config
(load_data_from_file config_encoding config_file_name)
Note that record_trace
takes a fully evaluated error err
as argument. It means that, whatever the value of the result res
, the error err
is evaluated. This is not an issue if the error is a simple expression (a literal or a constructor with simple parameters). However, for any expression that is more complex (e.g., one that calls a function) you should prefer record_trace_eval
.
val trace :
'err ->
('b, 'err TzTrace.trace) Stdlib.result Lwt.t ->
('b, 'err TzTrace.trace) Stdlib.result Lwt.t
trace
is identical to record_trace
but applies to a promise. More formally, trace err p
is a promise that resolves to Ok v
if p
resolves to Ok v
, or it resolves to Error (Trace.cons err tr)
if res
resolves to Error tr
.
In other words, trace err p
enriches the trace that p
resolves to (if it does resolve to a trace) with the error err
. It leaves the value that p
resolves to untouched if it is not a trace.
You can use this to add high-level information to potential low-level errors.
Note that, like record_trace
, trace
takes a fully evaluated error as argument. For a similar reason as explained there, you should only use trace
with simple expressions (literal or constructor with simple parameters) and prefer trace_eval
for any other expression (such as ones that include functions calls).
val record_trace_eval :
(unit -> 'err) ->
('a, 'err TzTrace.trace) Stdlib.result ->
('a, 'err TzTrace.trace) Stdlib.result
record_trace_eval
is identical to record_trace
except that the error that enriches the trace is wrapped in a function that is evaluated only if it is needed. More formally record_trace_eval mkerr res
is res
if res
is Ok _
, or it is Error (Trace.cons (mkerr ()) tr)
if res
is Error tr
.
You can achieve the same effect by hand with
match res with
| Ok _ -> res
| Error tr -> Error (Trace.cons (mkerr ()) tr)
Prefer record_trace_eval
over record_trace
when the enriching error is expensive to compute or heavy to allocate.
val trace_eval :
(unit -> 'err) ->
('b, 'err TzTrace.trace) Stdlib.result Lwt.t ->
('b, 'err TzTrace.trace) Stdlib.result Lwt.t
trace_eval
is identical to trace
except that the error that enriches the trace is wrapped in a function that is evaluated only if and when it is needed. More formally trace_eval mkerr p
is a promise that resolves to Ok v
if p
resolves to Ok v
, or it resolves to Error (Trace.cons err tr)
if p
resolves to Error tr
and then mkerr
()
resolves to err
.
You can achieve the same effect by hand with
p >>= function
| Ok _ -> p
| Error tr ->
mkerr () >>= fun err ->
Lwt.return (Error (Trace.cons err tr))
Note that the evaluation of the error can be arbitrarily delayed. Avoid using references and other mutable values in the function mkerr
.
Prefer trace_eval
over trace
when the enriching error is expensive to compute or heavy to allocate or when evaluating it requires the use of Lwt.
val error_unless : bool -> 'err -> (unit, 'err TzTrace.trace) Stdlib.result
error_unless flag err
is Ok ()
if b
is true
, it is Error (Trace.make err)
otherwise.
val error_when : bool -> 'err -> (unit, 'err TzTrace.trace) Stdlib.result
error_when flag err
is Error (Trace.make err)
if b
is true
, it is Ok ()
otherwise.
val fail_unless :
bool ->
'err ->
(unit, 'err TzTrace.trace) Stdlib.result Lwt.t
fail_unless flag err
is Lwt.return @@ Ok ()
if b
is true
, it is Lwt.return @@ Error (Trace.make err)
otherwise.
val fail_when : bool -> 'err -> (unit, 'err TzTrace.trace) Stdlib.result Lwt.t
fail_when flag err
is Lwt.return @@ Error (Trace.make err)
if b
is true
, it is Lwt.return @@ Ok ()
otherwise.
val unless :
bool ->
(unit -> (unit, 'trace) Stdlib.result Lwt.t) ->
(unit, 'trace) Stdlib.result Lwt.t
unless b f
is f ()
if b
is false
and it is a promise already resolved to Ok ()
otherwise.
You can use unless
to avoid having to write an if
statement that you then need to populate entirely to satisfy the type-checker. E.g, you can write unless b f
instead of if not b then f () else return_unit
.
val when_ :
bool ->
(unit -> (unit, 'trace) Stdlib.result Lwt.t) ->
(unit, 'trace) Stdlib.result Lwt.t
when_ b f
is f ()
if b
is true
and it is a promise already resolved to Ok ()
otherwise.
You can use when_
to avoid having to write an if
statement that you then need to populate entirely to satisfy the type-checker. E.g, you can write when_ b f
instead of if b then f () else return_unit
.