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
open! Import
module Stable = struct
module V1 = struct
type t =
| Jan
| Feb
| Mar
| Apr
| May
| Jun
| Jul
| Aug
| Sep
| Oct
| Nov
| Dec
[@@deriving sexp, sexp_grammar, compare, equal, hash, quickcheck, variants]
let failwithf = Printf.failwithf
let of_int_exn i : t =
match i with
| 1 -> Jan
| 2 -> Feb
| 3 -> Mar
| 4 -> Apr
| 5 -> May
| 6 -> Jun
| 7 -> Jul
| 8 -> Aug
| 9 -> Sep
| 10 -> Oct
| 11 -> Nov
| 12 -> Dec
| _ -> failwithf "Month.of_int_exn %d" i ()
;;
let of_int i =
try Some (of_int_exn i) with
| _ -> None
;;
let to_int (t : t) =
match t with
| Jan -> 1
| Feb -> 2
| Mar -> 3
| Apr -> 4
| May -> 5
| Jun -> 6
| Jul -> 7
| Aug -> 8
| Sep -> 9
| Oct -> 10
| Nov -> 11
| Dec -> 12
;;
let to_binable t = to_int t - 1
let of_binable i = of_int_exn (i + 1)
include
Binable.Stable.Of_binable.V1 [@alert "-legacy"]
(Int.Stable.V1)
(struct
type nonrec t = t
let to_binable = to_binable
let of_binable = of_binable
end)
include (val Comparator.Stable.V1.make ~compare ~sexp_of_t)
let stable_witness : t Stable_witness.t =
Stable_witness.of_serializable Int.Stable.V1.stable_witness of_binable to_binable
;;
end
end
let num_months = 12
module T = struct
include Stable.V1
let all = [ Jan; Feb; Mar; Apr; May; Jun; Jul; Aug; Sep; Oct; Nov; Dec ]
let hash = to_int
end
include T
include (
Hashable.Make_binable (struct
include T
end) :
Hashable.S_binable with type t := t)
include Comparable.Make_binable_using_comparator (struct
include T
let t_of_sexp sexp =
match Option.try_with (fun () -> Int.t_of_sexp sexp) with
| Some i -> of_int_exn (i + 1)
| None -> T.t_of_sexp sexp
;;
end)
let sexp_of_t = T.sexp_of_t
let t_of_sexp = T.t_of_sexp
let shift t i = of_int_exn (1 + Int.( % ) (to_int t - 1 + i) num_months)
let all_strings =
lazy
(Array.of_list (List.map all ~f:(fun variant -> Sexp.to_string (sexp_of_t variant))))
;;
let to_string (t : t) =
let all_strings = Lazy.force all_strings in
all_strings.(to_int t - 1)
;;
let of_string =
let table =
lazy
(let module T = String.Table in
let table = T.create ~size:num_months () in
Array.iteri (Lazy.force all_strings) ~f:(fun i s ->
let t = of_int_exn (i + 1) in
Hashtbl.set table ~key:s ~data:t;
Hashtbl.set table ~key:(String.lowercase s) ~data:t;
Hashtbl.set table ~key:(String.uppercase s) ~data:t);
table)
in
fun str ->
match Hashtbl.find (Lazy.force table) str with
| Some x -> x
| None -> failwithf "Invalid month: %s" str ()
;;
module Export = struct
type month = t =
| Jan
| Feb
| Mar
| Apr
| May
| Jun
| Jul
| Aug
| Sep
| Oct
| Nov
| Dec
end