Skip to content

Commit 5c333d0

Browse files
authored
Merge pull request #927 from MisterDA/lwt_result
Get `Lwt_result` closer to `Stdlib.Result`
2 parents 1edb00f + 982ea05 commit 5c333d0

File tree

4 files changed

+102
-14
lines changed

4 files changed

+102
-14
lines changed

CHANGES

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
====== Additions ======
99

1010
* In the Lwt_io module, add `?cloexec:bool` optional arguments to functions that create file descriptors (`pipe`). The `?cloexec` argument is simply forwarded to the wrapped Lwt_unix function. (#872, #911, Antonin Décimo)
11+
* Add Lwt_result.error, Lwt_result.iter, and Lwt_result.iter_error for consistency with Stdlib. (#927, Antonin Décimo)
1112

1213
====== Fixes ======
1314

@@ -16,6 +17,10 @@
1617
* Lwt.pick and Lwt.choose select preferentially failed promises as per
1718
documentation (#856, #874, Raman Varabets)
1819

20+
====== Deprecations ======
21+
22+
* Alias Lwt_result.map_err and Lwt_result.bind_lwt_err to Lwt_result.map_error and Lwt_result.bind_lwt_error for consistency with Stdlib. (#927, Antonin Décimo)
23+
1924
===== 5.5.0 =====
2025

2126
====== Deprecations ======

src/core/lwt_result.ml

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ let fail e = Lwt.return (Error e)
2020

2121
let lift = Lwt.return
2222
let ok x = Lwt.map (fun y -> Ok y) x
23+
let error x = Lwt.map (fun y -> Error y) x
2324

2425
let map f e =
2526
Lwt.map
@@ -28,12 +29,13 @@ let map f e =
2829
| Ok x -> Ok (f x))
2930
e
3031

31-
let map_err f e =
32+
let map_error f e =
3233
Lwt.map
3334
(function
3435
| Error e -> Error (f e)
3536
| Ok x -> Ok x)
3637
e
38+
let map_err f e = map_error f e
3739

3840
let catch e =
3941
Lwt.catch
@@ -65,11 +67,12 @@ let bind_result e f =
6567
| Ok x -> f x)
6668
e
6769

68-
let bind_lwt_err e f =
70+
let bind_lwt_error e f =
6971
Lwt.bind e
7072
(function
7173
| Error e -> Lwt.bind (f e) fail
7274
| Ok x -> return x)
75+
let bind_lwt_err e f = bind_lwt_error e f
7376

7477
let both a b =
7578
let s = ref None in
@@ -78,7 +81,7 @@ let both a b =
7881
| None -> s:= Some e
7982
| Some _ -> ()
8083
in
81-
let (a,b) = map_err set_once a,map_err set_once b in
84+
let (a,b) = map_error set_once a,map_error set_once b in
8285
let some_assert = function
8386
| None -> assert false
8487
| Some e -> Error e
@@ -87,10 +90,22 @@ let both a b =
8790
(function
8891
| Ok x, Ok y -> Ok (x,y)
8992
| Error _, Ok _
90-
| Ok _,Error _
93+
| Ok _,Error _
9194
| Error _, Error _ -> some_assert !s)
9295
(Lwt.both a b)
9396

97+
let iter f r =
98+
Lwt.bind r
99+
(function
100+
| Ok x -> f x
101+
| Error _ -> Lwt.return_unit)
102+
103+
let iter_error f r =
104+
Lwt.bind r
105+
(function
106+
| Error e -> f e
107+
| Ok _ -> Lwt.return_unit)
108+
94109
module Infix = struct
95110
let (>>=) = bind
96111
let (>|=) e f = map f e

src/core/lwt_result.mli

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ val lift : ('a, 'b) result -> ('a, 'b) t
2020

2121
val ok : 'a Lwt.t -> ('a, _) t
2222

23+
val error : 'b Lwt.t -> (_, 'b) t
24+
(** @since 5.6.0 *)
25+
2326
val catch : 'a Lwt.t -> ('a, exn) t
2427
(** [catch x] behaves like [return y] if [x] evaluates to [y],
2528
and like [fail e] if [x] raises [e] *)
@@ -31,13 +34,15 @@ val get_exn : ('a, exn) t -> 'a Lwt.t
3134

3235
val map : ('a -> 'b) -> ('a,'e) t -> ('b,'e) t
3336

34-
val map_err : ('e1 -> 'e2) -> ('a,'e1) t -> ('a,'e2) t
37+
val map_error : ('e1 -> 'e2) -> ('a,'e1) t -> ('a,'e2) t
38+
(** @since 5.6.0 *)
3539

3640
val bind : ('a,'e) t -> ('a -> ('b,'e) t) -> ('b,'e) t
3741

3842
val bind_lwt : ('a,'e) t -> ('a -> 'b Lwt.t) -> ('b,'e) t
3943

40-
val bind_lwt_err : ('a,'e1) t -> ('e1 -> 'e2 Lwt.t) -> ('a,'e2) t
44+
val bind_lwt_error : ('a,'e1) t -> ('e1 -> 'e2 Lwt.t) -> ('a,'e2) t
45+
(** @since 5.6.0 *)
4146

4247
val bind_result : ('a,'e) t -> ('a -> ('b,'e) result) -> ('b,'e) t
4348

@@ -49,6 +54,19 @@ val both : ('a,'e) t -> ('b,'e) t -> ('a * 'b,'e) t
4954
If both [p_1] and [p_2] resolve with [Error _], the promise is resolved with
5055
the error that occurred first. *)
5156

57+
val iter : ('a -> unit Lwt.t) -> ('a, 'e) t -> unit Lwt.t
58+
(** [iter f r] is [f v] if [r] is a promise resolved with [Ok v], and
59+
{!Lwt.return_unit} otherwise.
60+
61+
@since Lwt 5.6.0
62+
*)
63+
64+
val iter_error : ('e -> unit Lwt.t) -> ('a, 'e) t -> unit Lwt.t
65+
(** [iter_error f r] is [f v] if [r] is a promise resolved with [Error v],
66+
and {!Lwt.return_unit} otherwise.
67+
68+
@since Lwt 5.6.0
69+
*)
5270

5371
module Infix : sig
5472
val (>|=) : ('a,'e) t -> ('a -> 'b) -> ('b,'e) t
@@ -95,3 +113,11 @@ module Syntax : sig
95113
end
96114

97115
include module type of Infix
116+
117+
(** {3 Deprecated} *)
118+
119+
val map_err : ('e1 -> 'e2) -> ('a,'e1) t -> ('a,'e2) t [@@deprecated "Alias to map_error"]
120+
(** @deprecated Alias to [map_error] since 5.6.0. *)
121+
122+
val bind_lwt_err : ('a,'e1) t -> ('e1 -> 'e2 Lwt.t) -> ('a,'e2) t [@@deprecated "Alias to bind_lwt_error"]
123+
(** @deprecated Alias to [bind_lwt_error] since 5.6.0. *)

test/core/test_lwt_result.ml

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,17 @@ let suite =
3838
Lwt.return (Lwt_result.map ((+) 1) x = x)
3939
);
4040

41-
test "map_err"
41+
test "map_error"
4242
(fun () ->
4343
let x = Lwt_result.return 0 in
44-
Lwt.return (Lwt_result.map_err ((+) 1) x = x)
44+
Lwt.return (Lwt_result.map_error ((+) 1) x = x)
4545
);
4646

47-
test "map_err, error case"
47+
test "map_error, error case"
4848
(fun () ->
4949
let x = Lwt_result.fail 0 in
5050
let correct = Lwt_result.fail 1 in
51-
Lwt.return (Lwt_result.map_err ((+) 1) x = correct)
51+
Lwt.return (Lwt_result.map_error ((+) 1) x = correct)
5252
);
5353

5454
test "bind"
@@ -72,6 +72,12 @@ let suite =
7272
Lwt.return (Lwt_result.ok x = Lwt_result.return 0)
7373
);
7474

75+
test "error"
76+
(fun () ->
77+
let x = Lwt.return 0 in
78+
Lwt.return (Lwt_result.error x = Lwt_result.fail 0)
79+
);
80+
7581
test "catch"
7682
(fun () ->
7783
let x = Lwt.return 0 in
@@ -110,18 +116,18 @@ let suite =
110116
Lwt.return (Lwt_result.bind_lwt x f = Lwt_result.fail 0)
111117
);
112118

113-
test "bind_lwt_err"
119+
test "bind_lwt_error"
114120
(fun () ->
115121
let x = Lwt_result.return 0 in
116122
let f y = Lwt.return (y + 1) in
117-
Lwt.return (Lwt_result.bind_lwt_err x f = Lwt_result.return 0)
123+
Lwt.return (Lwt_result.bind_lwt_error x f = Lwt_result.return 0)
118124
);
119125

120-
test "bind_lwt_err, error case"
126+
test "bind_lwt_error, error case"
121127
(fun () ->
122128
let x = Lwt_result.fail 0 in
123129
let f y = Lwt.return (y + 1) in
124-
Lwt.return (Lwt_result.bind_lwt_err x f = Lwt_result.fail 1)
130+
Lwt.return (Lwt_result.bind_lwt_error x f = Lwt_result.fail 1)
125131
);
126132

127133
test "bind_result"
@@ -192,6 +198,42 @@ let suite =
192198
Lwt.bind p (fun x -> Lwt.return (x = Result.Error 1))
193199
);
194200

201+
test "iter"
202+
(fun () ->
203+
let x = Lwt_result.return 1 in
204+
let actual = ref 0 in
205+
Lwt.bind
206+
(Lwt_result.iter (fun y -> actual := y + 1; Lwt.return_unit) x)
207+
(fun () -> Lwt.return (!actual = 2))
208+
);
209+
210+
test "iter, error case"
211+
(fun () ->
212+
let x = Lwt_result.fail 1 in
213+
let actual = ref 0 in
214+
Lwt.bind
215+
(Lwt_result.iter (fun y -> actual := y + 1; Lwt.return_unit) x)
216+
(fun () -> Lwt.return (!actual <> 2))
217+
);
218+
219+
test "iter_error"
220+
(fun () ->
221+
let x = Lwt_result.fail 1 in
222+
let actual = ref 0 in
223+
Lwt.bind
224+
(Lwt_result.iter_error (fun y -> actual := y + 1; Lwt.return_unit) x)
225+
(fun () -> Lwt.return (!actual = 2))
226+
);
227+
228+
test "iter_error, success case"
229+
(fun () ->
230+
let x = Lwt_result.return 1 in
231+
let actual = ref 0 in
232+
Lwt.bind
233+
(Lwt_result.iter_error (fun y -> actual := y + 1; Lwt.return_unit) x)
234+
(fun () -> Lwt.return (!actual <> 2))
235+
);
236+
195237
test "let*"
196238
(fun () ->
197239
let p1, r1 = Lwt.wait () in

0 commit comments

Comments
 (0)