···150150151151### Standard library:
152152153153+- #13696: Add Result.product and Result.Syntax.
154154+ (Daniel Bünzli, review by Gabriel Scherer, Nicolás Ojeda Bär)
155155+153156- #13885: Add Dynarray.{exists2, for_all2}.
154157 (T. Kinsart, review by Daniel Bünzli, Gabriel Scherer, and Nicolás Ojeda Bär)
155158
+12
stdlib/result.ml
···2323let bind r f = match r with Ok v -> f v | Error _ as e -> e
2424let join = function Ok r -> r | Error _ as e -> e
2525let map f = function Ok v -> Ok (f v) | Error _ as e -> e
2626+let product r0 r1 = match r0, r1 with
2727+| (Error _ as r), _
2828+| _, (Error _ as r) -> r
2929+| Ok v0, Ok v1 -> Ok (v0, v1)
3030+2631let map_error f = function Error e -> Error (f e) | Ok _ as v -> v
2732let fold ~ok ~error = function Ok v -> ok v | Error e -> error e
2833let retract = function Ok v -> v | Error v -> v
···4550let to_option = function Ok v -> Some v | Error _ -> None
4651let to_list = function Ok v -> [v] | Error _ -> []
4752let to_seq = function Ok v -> Seq.return v | Error _ -> Seq.empty
5353+5454+module Syntax = struct
5555+ let ( let* ) = bind
5656+ let ( and* ) = product
5757+ let ( let+ ) r f = map f r
5858+ let ( and+ ) = product
5959+end
+26
stdlib/result.mli
···5353val map : ('a -> 'b) -> ('a, 'e) result -> ('b, 'e) result
5454(** [map f r] is [Ok (f v)] if [r] is [Ok v] and [r] if [r] is [Error _]. *)
55555656+val product : ('a, 'e) result -> ('b, 'e) result -> ('a * 'b, 'e) result
5757+(** [product r0 r1] is [Ok (v0, v1)] if [r0] is [Ok v0] and [r1] is [Ok v2]
5858+ and otherwise returns the error of [r0], if any, or the error of [r1].
5959+6060+ @since 5.4 *)
6161+5662val map_error : ('e -> 'f) -> ('a, 'e) result -> ('a, 'f) result
5763(** [map_error f r] is [Error (f e)] if [r] is [Error e] and [r] if
5864 [r] is [Ok _]. *)
···106112val to_seq : ('a, 'e) result -> 'a Seq.t
107113(** [to_seq r] is [r] as a sequence. [Ok v] is the singleton sequence
108114 containing [v] and [Error _] is the empty sequence. *)
115115+116116+(** {1:syntax Syntax} *)
117117+118118+(** Binding operators.
119119+120120+ @since 5.4 *)
121121+module Syntax : sig
122122+123123+ val ( let* ) : ('a, 'e) result -> ('a -> ('b, 'e) result) -> ('b, 'e) result
124124+ (** [( let* )] is {!Result.bind}. *)
125125+126126+ val ( and* ) : ('a, 'e) result -> ('b, 'e) result -> ('a * 'b, 'e) result
127127+ (** [( and* )] is {!Result.product}. *)
128128+129129+ val ( let+ ) : ('a, 'e) result -> ('a -> 'b) -> ('b, 'e) result
130130+ (** [( let+ )] is {!Result.map}. *)
131131+132132+ val ( and+ ) : ('a, 'e) result -> ('b, 'e) result -> ('a * 'b, 'e) result
133133+ (** [( and+ )] is {!Result.product}. *)
134134+end
+26
testsuite/tests/lib-result/test.ml
···4242 assert (Result.map_error succ (Ok 2) = Ok 2);
4343 ()
44444545+let test_product () =
4646+ assert (Result.product (Ok "a") (Ok 3) = Ok ("a", 3));
4747+ assert (Result.product (Ok "a") (Error "ha") = Error "ha");
4848+ assert (Result.product (Error "hi") (Error "ha") = Error "hi");
4949+ assert (Result.product (Error "hi") (Ok 3) = Error "hi");
5050+ ()
5151+4552let test_fold () =
4653 assert (Result.fold ~ok:succ ~error:succ (Ok 1) = 2);
4754 assert (Result.fold ~ok:succ ~error:succ (Error 1) = 2);
···115122 assert ((Result.to_seq (Error "ha!")) () = Seq.Nil);
116123 ()
117124125125+let test_syntax () =
126126+ let open Result.Syntax in
127127+ assert (Ok 5 =
128128+ let parse n = Ok n in
129129+ let* n0 = parse 3 in
130130+ let* n1 = parse 2 in
131131+ Ok (n0 + n1));
132132+ assert (Ok 3 =
133133+ let+ one = Ok 1
134134+ and+ two = Ok 2 in
135135+ one + two);
136136+ assert (Ok 1 =
137137+ let* three = Ok 3 in
138138+ let+ two = Ok 2 in
139139+ three - two);
140140+ ()
141141+118142let tests () =
119143 test_ok_error ();
120144 test_value ();
···122146 test_bind ();
123147 test_join ();
124148 test_maps ();
149149+ test_product ();
125150 test_fold ();
126151 test_retract ();
127152 test_iters ();
···129154 test_equal ();
130155 test_compare ();
131156 test_to_option_list_seq ();
157157+ test_syntax ();
132158 ()
133159134160let () =