package base

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file either.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
open! Import

include Either_intf

module Array = Array0

type ('f, 's) t =
  | First  of 'f
  | Second of 's
[@@deriving_inline compare, hash, sexp]
let compare :
  'f 's .
  ('f -> 'f -> int) -> ('s -> 's -> int) -> ('f, 's) t -> ('f, 's) t -> int
  =
  fun _cmp__f ->
  fun _cmp__s ->
  fun a__001_ ->
  fun b__002_ ->
    if Ppx_compare_lib.phys_equal a__001_ b__002_
    then 0
    else
      (match (a__001_, b__002_) with
       | (First _a__003_, First _b__004_) -> _cmp__f _a__003_ _b__004_
       | (First _, _) -> (-1)
       | (_, First _) -> 1
       | (Second _a__005_, Second _b__006_) ->
         _cmp__s _a__005_ _b__006_)
let hash_fold_t : type f s.
  (Ppx_hash_lib.Std.Hash.state -> f -> Ppx_hash_lib.Std.Hash.state) ->
  (Ppx_hash_lib.Std.Hash.state -> s -> Ppx_hash_lib.Std.Hash.state) ->
  Ppx_hash_lib.Std.Hash.state -> (f, s) t -> Ppx_hash_lib.Std.Hash.state
  =
  fun _hash_fold_f ->
  fun _hash_fold_s ->
  fun hsv ->
  fun arg ->
    match arg with
    | First _a0 ->
      let hsv = Ppx_hash_lib.Std.Hash.fold_int hsv 0 in
      let hsv = hsv in _hash_fold_f hsv _a0
    | Second _a0 ->
      let hsv = Ppx_hash_lib.Std.Hash.fold_int hsv 1 in
      let hsv = hsv in _hash_fold_s hsv _a0
let t_of_sexp : type f s.
  (Ppx_sexp_conv_lib.Sexp.t -> f) ->
  (Ppx_sexp_conv_lib.Sexp.t -> s) -> Ppx_sexp_conv_lib.Sexp.t -> (f, s) t
  =
  let _tp_loc = "src/either.ml.t" in
  fun _of_f ->
  fun _of_s ->
    function
    | Ppx_sexp_conv_lib.Sexp.List ((Ppx_sexp_conv_lib.Sexp.Atom
                                      ("first"|"First" as _tag))::sexp_args) as _sexp ->
      (match sexp_args with
       | v0::[] -> let v0 = _of_f v0 in First v0
       | _ ->
         Ppx_sexp_conv_lib.Conv_error.stag_incorrect_n_args _tp_loc
           _tag _sexp)
    | Ppx_sexp_conv_lib.Sexp.List ((Ppx_sexp_conv_lib.Sexp.Atom
                                      ("second"|"Second" as _tag))::sexp_args) as _sexp ->
      (match sexp_args with
       | v0::[] -> let v0 = _of_s v0 in Second v0
       | _ ->
         Ppx_sexp_conv_lib.Conv_error.stag_incorrect_n_args _tp_loc
           _tag _sexp)
    | Ppx_sexp_conv_lib.Sexp.Atom ("first"|"First") as sexp ->
      Ppx_sexp_conv_lib.Conv_error.stag_takes_args _tp_loc sexp
    | Ppx_sexp_conv_lib.Sexp.Atom ("second"|"Second") as sexp ->
      Ppx_sexp_conv_lib.Conv_error.stag_takes_args _tp_loc sexp
    | Ppx_sexp_conv_lib.Sexp.List ((Ppx_sexp_conv_lib.Sexp.List _)::_) as
      sexp ->
      Ppx_sexp_conv_lib.Conv_error.nested_list_invalid_sum _tp_loc sexp
    | Ppx_sexp_conv_lib.Sexp.List [] as sexp ->
      Ppx_sexp_conv_lib.Conv_error.empty_list_invalid_sum _tp_loc sexp
    | sexp -> Ppx_sexp_conv_lib.Conv_error.unexpected_stag _tp_loc sexp
let sexp_of_t : type f s.
  (f -> Ppx_sexp_conv_lib.Sexp.t) ->
  (s -> Ppx_sexp_conv_lib.Sexp.t) -> (f, s) t -> Ppx_sexp_conv_lib.Sexp.t
  =
  fun _of_f ->
  fun _of_s ->
    function
    | First v0 ->
      let v0 = _of_f v0 in
      Ppx_sexp_conv_lib.Sexp.List
        [Ppx_sexp_conv_lib.Sexp.Atom "First"; v0]
    | Second v0 ->
      let v0 = _of_s v0 in
      Ppx_sexp_conv_lib.Sexp.List
        [Ppx_sexp_conv_lib.Sexp.Atom "Second"; v0]
[@@@end]

let swap = function
  | First  x -> Second x
  | Second x -> First  x
;;

let is_first = function
  | First  _ -> true
  | Second _ -> false
;;

let is_second = function
  | First  _ -> false
  | Second _ -> true
;;

let value (First x | Second x) = x
;;

let value_map t ~first ~second =
  match t with
  | First x -> first x
  | Second x -> second x
;;

let iter = value_map
;;

let map t ~first ~second =
  match t with
  | First x -> First (first x)
  | Second x -> Second (second x)
;;

let first  x = First  x
let second x = Second x
;;

let equal eq1 eq2 t1 t2 =
  match t1, t2 with
  | First  x, First  y -> eq1 x y
  | Second x, Second y -> eq2 x y
  | First  _, Second _
  | Second _, First  _ -> false
;;

let invariant f s = function
  | First  x -> f x
  | Second y -> s y
;;

module Make_focused (M : sig
    type (+'a, +'b) t

    val return : 'a -> ('a, _) t
    val other  : 'b -> (_, 'b) t

    val either  : ('a, 'b) t -> return:('a -> 'c) -> other:('b -> 'c) -> 'c

    val combine
      :  ('a, 'd) t
      -> ('b, 'd) t
      -> f:('a -> 'b -> 'c)
      -> other:('d -> 'd -> 'd)
      -> ('c, 'd) t
  end) = struct
  include M
  open With_return

  let map t ~f = either t ~return:(fun x -> return (f x)) ~other

  include Monad.Make2 (struct
      type nonrec ('a, 'b) t = ('a, 'b) t

      let return = return
      ;;

      let bind t ~f = either t ~return:f ~other
      ;;

      let map = `Custom map
    end)

  module App = Applicative.Make2 (struct
      type nonrec ('a, 'b) t = ('a, 'b) t

      let return = return
      ;;

      let apply t1 t2 =
        let return f = either t2 ~return:(fun x -> return (f x)) ~other in
        either t1 ~return ~other
      ;;

      let map = `Custom map
    end)

  include App

  module Args = Applicative.Make_args2 (struct
      type nonrec ('a, 'b) t = ('a, 'b) t
      include App
    end)
  [@@warning "-3"]

  let combine_all =
    let rec other_loop f acc = function
      | [] -> other acc
      | t :: ts ->
        either t ~return:(fun _ -> other_loop f acc ts)
          ~other:(fun o -> other_loop f (f acc o) ts)
    in
    let rec return_loop f acc = function
      | [] -> return (List.rev acc)
      | t :: ts ->
        either t ~return:(fun x -> return_loop f (x :: acc) ts)
          ~other:(fun o -> other_loop f o ts)
    in
    fun ts ~f -> return_loop f [] ts
  ;;

  let combine_all_unit =
    let rec other_loop f acc = function
      | [] -> other acc
      | t :: ts ->
        either t ~return:(fun () -> other_loop f acc ts)
          ~other:(fun o -> other_loop f (f acc o) ts)
    in
    let rec return_loop f = function
      | [] -> return ()
      | t :: ts ->
        either t ~return:(fun () -> return_loop f ts)
          ~other:(fun o -> other_loop f o ts)
    in
    fun ts ~f -> return_loop f ts
  ;;

  let to_option t = either t ~return:Option.some ~other:(fun _ -> None)
  ;;

  let value t ~default = either t ~return:Fn.id ~other:(fun _ -> default)
  ;;

  let with_return f =
    with_return (fun ret ->
      other (f (With_return.prepend ret ~f:return)))
  ;;

end

module First = Make_focused (struct
    type nonrec ('a, 'b) t = ('a, 'b) t

    let return = first
    let other  = second
    ;;

    let either t ~return ~other =
      match t with
      | First  x -> return x
      | Second y -> other  y
    ;;

    let combine t1 t2 ~f ~other =
      match t1, t2 with
      | First x, First y -> First (f x y)
      | Second x, Second y -> Second (other x y)
      | Second x, _
      | _, Second x -> Second x
  end)

module Second = Make_focused (struct
    type nonrec ('a, 'b) t = ('b, 'a) t

    let return = second
    let other  = first
    ;;

    let either t ~return ~other =
      match t with
      | Second y -> return y
      | First  x -> other  x
    ;;

    let combine t1 t2 ~f ~other =
      match t1, t2 with
      | Second x, Second y -> Second (f x y)
      | First x, First y -> First (other x y)
      | First x, _
      | _, First x -> First x
  end)

module Export = struct
  type ('f, 's) _either
    = ('f, 's) t
    = First  of 'f
    | Second of 's
end
OCaml

Innovation. Community. Security.