Module Monad.Lwt_result_syntax

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.

See also Lwt, Result, and Lwt_result.

val return : 'a -> ('a, 'e) Stdlib.result Lwt.t

return x is Lwt.return (Ok x) or Lwt_result.return x.

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

return_unit is Lwt.return (Ok ()) .

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

return_none is Lwt.return (Ok None) .

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

return_some x is Lwt.return (Ok (Some x)) .

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

return_nil is Lwt.return (Ok []) .

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

return_true is Lwt.return (Ok true) .

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

return_false is Lwt.return (Ok false) .

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 …).

val fail : 'e -> ('a, 'e) Stdlib.result Lwt.t

fail e is Lwt.return (Error e).

val let* : ('a, 'e) Stdlib.result Lwt.t -> ('a -> ('b, 'e) Stdlib.result Lwt.t) -> ('b, 'e) Stdlib.result Lwt.t

let* is a binding operator alias for Lwt_result.bind.

val let+ : ('a, 'e) Stdlib.result Lwt.t -> ('a -> 'b) -> ('b, 'e) Stdlib.result Lwt.t

let+ is a binding operator alias for Lwt_result.map.

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.

val lwt_map_error : ('e -> 'f) -> ('a, 'e) Stdlib.result Lwt.t -> ('a, 'f) Stdlib.result Lwt.t

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.

val let*! : 'a Lwt.t -> ('a -> 'b Lwt.t) -> 'b Lwt.t

let*! is for binding Lwt-only expressions into the LwtResult combined monad.

let open Lwt_result_syntax in
let* x = … in
let*! y = … in
return (x + y)
val let*? : ('a, 'e) Stdlib.result -> ('a -> ('b, 'e) Stdlib.result Lwt.t) -> ('b, 'e) Stdlib.result Lwt.t

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
val join : (unit, 'e) Stdlib.result Lwt.t list -> (unit, 'e list) Stdlib.result Lwt.t

join is the joining of concurrent success/failure unit values.

val all : ('a, 'e) Stdlib.result Lwt.t list -> ('a list, 'e list) Stdlib.result Lwt.t

all is the joining of concurrent success/failure non-unit values.

val both : ('a, 'e) Stdlib.result Lwt.t -> ('b, 'e) Stdlib.result Lwt.t -> ('a * 'b, 'e list) Stdlib.result Lwt.t

both is the joining of two concurrent success/failure non-unit values.