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
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 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 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 t =
| Nil : t
| Cons : 'a Deferred0.t * 'a Deferred0.Handler.t * t -> t
let rec process = function
| Nil -> ()
| Cons (t, 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 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, _)) ->
Cons (t, Deferred0.add_handler t ready execution_context, acc));
Ivar.read result
;;
let rec choose_result choices =
match choices with
| [] -> assert false
| Choice.T (t, f) :: choices ->
(match peek t with
| None -> choose_result choices
| Some v -> f v)
;;
let choose 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 result (choose_result choices))
in
let execution_context = Scheduler.(current_execution_context (t ())) in
unregisters
:= List.fold choices ~init:Unregister.Nil ~f:(fun acc (Choice.T (t, _)) ->
Cons (t, Deferred0.add_handler t ready execution_context, acc));
Ivar.read result
;;
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_ =
let rec loop i =
if i > to_
then return ()
else (
let%bind () = do_ i in
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 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 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