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
open Core
module Scheduler = Scheduler1
include Deferred0
let never () = Ivar.read (Ivar.create ())
module M = Monad.Make (struct
include Deferred0
let map t ~f =
let result = Ivar.create () in
upon t (fun a -> Ivar.fill_exn result (f a));
of_ivar result
;;
let map = `Custom map
end)
include M
let return = Deferred0.return
module Let_syntax = struct
include M.Let_syntax
let return = Deferred0.return
module Let_syntax = struct
include M.Let_syntax.Let_syntax
let return = Deferred0.return
end
end
open Let_syntax
let all = `Make_sure_to_define_all_elsewhere
let _ = all
let unit = return ()
let both t1 t2 =
create (fun result ->
upon t1 (fun a1 -> upon t2 (fun a2 -> Ivar.fill_exn result (a1, a2))))
;;
module Infix = struct
include Monad_infix
let ( >>> ) = upon
let ppx_both = both
end
open Infix
let don't_wait_for (_ : unit t) = ()
module Choice = struct
type +'a t = T : 'b Deferred0.t * ('b -> 'a) -> 'a t
let map (T (t, f1)) ~f:f2 = T (t, fun x -> f2 (f1 x))
end
module Unregister = struct
type 'r t =
| Nil : 'r t
| Cons : 'a Deferred0.t * ('a -> 'r) * 'a Deferred0.Handler.t * 'r t -> 'r t
let rec process = function
| Nil -> ()
| Cons (t, _f, handler, rest) ->
remove_handler t handler;
process rest
;;
end
let choice t f = Choice.T (t, f)
let enabled choices =
let result = Ivar.create () in
let unregisters = ref Unregister.Nil in
let ready _ =
if Ivar.is_empty result
then (
Unregister.process !unregisters;
Ivar.fill_exn result (fun () ->
List.rev
(List.fold choices ~init:[] ~f:(fun ac (Choice.T (t, f)) ->
match peek t with
| None -> ac
| Some v -> f v :: ac))))
in
let execution_context = Scheduler.(current_execution_context (t ())) in
unregisters
:= List.fold choices ~init:Unregister.Nil ~f:(fun acc (Choice.T (t, f)) ->
Cons (t, f, Deferred0.add_handler t ready execution_context, acc));
Ivar.read result
;;
let rec choose_result choices =
match choices with
| Unregister.Nil -> assert false
| Unregister.Cons (t, f, _, rest) ->
(match peek t with
| None -> choose_result rest
| Some v -> f v)
;;
let generic_choose choices =
let result = Ivar.create () in
let execution_context = Scheduler.(current_execution_context (t ())) in
let rec unregisters =
lazy
(List.fold_right choices ~init:Unregister.Nil ~f:(fun (Choice.T (t, f)) acc ->
Unregister.Cons (t, f, Deferred0.add_handler t ready execution_context, acc)))
and ready : 'a. 'a -> unit =
fun _ ->
if Ivar.is_empty result
then (
let unregisters = Lazy.force unregisters in
Unregister.process unregisters;
Ivar.fill_exn result (choose_result unregisters))
in
let (_ : _) = Lazy.force unregisters in
Ivar.read result
;;
let choose2 a fa b fb =
let result = Ivar.create () in
let execution_context = Scheduler.(current_execution_context (t ())) in
let rec a_handler = lazy (Deferred0.add_handler a ready execution_context)
and b_handler = lazy (Deferred0.add_handler b ready execution_context)
and ready : 'a. 'a -> unit =
fun _ ->
if Ivar.is_empty result
then (
remove_handler a (Lazy.force a_handler);
remove_handler b (Lazy.force b_handler);
match peek a with
| Some av -> Ivar.fill_exn result (fa av)
| None -> Ivar.fill_exn result (fb (value_exn b)))
in
let (_ : _) = Lazy.force a_handler in
let (_ : _) = Lazy.force b_handler in
Ivar.read result
;;
let choose choices =
match choices with
| [ Choice.T (a, fa); Choice.T (b, fb) ] -> choose2 a fa b fb
| choices -> generic_choose choices
;;
let any_f ts f = choose (List.map ts ~f:(fun t -> choice t f))
let any ts = any_f ts Fn.id
let any_unit ts = any_f ts (Fn.ignore : unit -> unit)
let for_ start ~to_ ~do_ =
if start > to_
then return ()
else (
let rec loop i =
let%bind () = do_ i in
if i >= to_ then return () else loop (i + 1)
in
loop start)
;;
let repeat_until_finished state f =
create (fun finished ->
let rec loop state =
f state
>>> function
| `Repeat state -> loop state
| `Finished result -> Ivar.fill_exn finished result
in
loop state)
;;
let forever state f =
repeat_until_finished state (fun state ->
let%map state = f state in
`Repeat state)
>>> never_returns
;;
type how = Monad_sequence.how [@@deriving sexp_of]
module type Monad_sequence = Monad_sequence.S with type 'a monad := 'a t
let fold t ~init ~f =
create (fun result ->
let rec loop t b =
match t with
| [] -> Ivar.fill_exn result b
| x :: xs -> f b x >>> fun b -> loop xs b
in
loop t init)
;;
let seqmap t ~f = fold t ~init:[] ~f:(fun bs a -> f a >>| fun b -> b :: bs) >>| List.rev
let all ds = seqmap ds ~f:Fn.id
let all_unit ds = fold ds ~init:() ~f:(fun () d -> d)
let ok x = x >>| fun x -> Ok x
module For_tests = struct
let generic_choose = generic_choose
end