-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathUtil.ml
128 lines (105 loc) · 4.12 KB
/
Util.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
module Int8 : sig
(** Represents an 8-bit integer. *)
type t = private int
(** [to_int value] converts [value] to a built-in integer. *)
val to_int : t -> int
(** [of_int value] converts [value] to an 8-bit integer.
Returns [None] if [value] does not fit in 8 bits. *)
val of_int : int -> t option
(** [of_int_exn value] converts [value] to a 8-bit integer.
Raises a [Failure] exception if [value] does not fit in 8
bits. *)
val of_int_exn : int -> t
end = struct
type t = int
let to_int : t -> int = fun value -> value
let of_int (value : int) : t option =
if not (0 <= value && value < 256) then None else Some value
;;
let of_int_exn (value : int) : t =
match of_int value with
| None -> failwith "expected an integer between 0 and 255 (both included)"
| Some value' -> value'
;;
end
module Pair = struct
type ('a, 'b) t = 'a * 'b
let first : ('a, 'b) t -> 'a = fun (first, _) -> first
let second : ('a, 'b) t -> 'b = fun (_, second) -> second
let map : ('a -> 'c) -> ('b -> 'd) -> ('a, 'b) t -> ('c, 'd) t =
fun func_first func_second (first, second) -> func_first first, func_second second
;;
let map_first : ('a -> 'c) -> ('a, 'b) t -> ('c, 'b) t =
fun func pair -> map func Fun.id pair
;;
let map_second : ('b -> 'c) -> ('a, 'b) t -> ('a, 'c) t =
fun func pair -> map Fun.id func pair
;;
let map_uniform : ('a -> 'b) -> ('a, 'a) t -> ('b, 'b) t =
fun func pair -> map func func pair
;;
end
module Triplet = struct
type ('a, 'b, 'c) t = 'a * 'b * 'c
(** [all triplet] returns a version of [triplet] wrapped in
[option], which is of the [Some] variant if every member
is also of the [Some variant], [None] otherwise. *)
let all : ('a option, 'b option, 'c option) t -> ('a, 'b, 'c) t option = function
| Some first, Some second, Some third -> Some (first, second, third)
| _ -> None
;;
(** [all_ok triplet] returns a version of [triplet] wrapped in
[result], which is of the [Ok] variant if every member
is also of the [Ok] variant, otherwise it is whichever
is the first [Error]. *)
let all_ok
: (('a, 'e) result, ('b, 'e) result, ('c, 'e) result) t -> (('a, 'b, 'c) t, 'e) result
= function
| Ok first, Ok second, Ok third -> Ok (first, second, third)
| (Error _ as error), _, _ -> error
| _, (Error _ as error), _ -> error
| _, _, (Error _ as error) -> error
;;
(** [all_error triplet] returns a version of [triplet] wrapped in
[result], which is of the [Error] variant if every member
is also of the [Error] variant, otherwise it is whichever
is the first [Ok]. *)
let all_error (* Somehow ocamlformat leaves two spaces after the colon *)
: (('r, 'e1) result, ('r, 'e2) result, ('r, 'e3) result) t
-> ('r, ('e1, 'e2, 'e3) t) result
= function
| Error first, Error second, Error third -> Error (first, second, third)
| (Ok _ as ok), _, _ -> ok
| _, (Ok _ as ok), _ -> ok
| _, _, (Ok _ as ok) -> ok
;;
(** [any_ok triplet] returns a version of [triplet] wrapped
in [result], which is the first [Ok] encountered if there
is any, otherwise it is the triplet wrapped in [Error].
It is the same as [all_error], but it is semantically
useful to have it as a separate function. *)
let any_ok = all_error
(** [map func1 func2 func3 triplet] produces a new triplet
where each member is mapped to its corresponding function.
That is, if [triplet] is [(first, second, third)], the
result will be [(func1 first, func2 second, func3 third)]. *)
let map (func1 : 'a -> 'd) (func2 : 'b -> 'e) (func3 : 'c -> 'f)
: ('a, 'b, 'c) t -> ('d, 'e, 'f) t
= function
| first, second, third -> func1 first, func2 second, func3 third
;;
(** [map_uniform func triplet] maps [func] to every member of
the triplet.
It is equivalent to [map func func func triplet]. *)
let map_uniform ~(func : 'a -> 'b) : ('a, 'a, 'a) t -> ('b, 'b, 'b) t =
map func func func
;;
end
module Option = struct
include Option
let last left right =
match right with
| Some _ -> right
| None -> left
;;
end