Legend:
Library
Module
Module type
Parameter
Class
Class type
Syntax module for Lwt+Result. This is intended to be opened locally in functions which use Lwt and result for control-flow. Within the scope of this module, the code can include binding operators, leading to a let-style syntax.
Note that we do not provide return_ok nor return_error. Both of these functions are possible but somewhat confusing and rarely useful in practice. If you need to carry results within a LwtResult-monad computation (yielding values of the type (('a, 'e) result, 'e) result Lwt.t), you need to do so by hand: return (Ok …) and return (Error …).
Note that we do not provide and* nor and+. Both of these are possible but their type is unsatisfying because the errors do not compose well. You can use both (below) if need be.
lwt_map_error is an Lwt-aware variant of Result.map_error. It is intended for mapping the errors of Lwt-result values. The main use of this function is for mixing results that carry different types of errors.
E.g., considering fetch : unit -> (string, unit) result Lwt.t and emit : string -> (unit, int) result Lwt.t, you can write
let* data = lwt_map_error (fun () -> "fetching failed") @@ fetch () in
let* () =
lwt_map_error (fun code -> Format.asprintf "emit failed (%d)")
@@ emit data
in
..
The following values are for mixing expressions that are Lwt-only or Result-only within the LwtResult monad. Note that there are fundamental differences between result and Lwt.t: the former can be simply matched on (i.e., it is possible to get out of the monad at any point) whereas the latter can only be bound on (i.e., it is not possible to get out of the monad). In addition, the former is for aborting computations on failures whereas the latter is for waiting before continuing.
Still, from a syntax point-of-view, both are handled the same way: with a specialised binding operator.
let*? is for binding the value from Result-only expressions into the LwtResult combined monad.
let open Lwt_result_syntax in
let* x = … in
let*? y = … in
…
Note that you can mix let*, let*!, and let*? as needed, within a single expression.
let do_thing param =
let open Lwt_result_syntax in
let*? () = check_p param in (* Result-only for parameter checking *)
let*! () = log "starting doing the thing" in (* Lwt-only for infallible logging *)
let* r = thing param in
let*! () = log "done doing the thing" in (* Lwt-only for infallible logging *)
return r