-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreactMap.eliom
178 lines (160 loc) · 4.87 KB
/
reactMap.eliom
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
[%%server
module Make(O : Map.OrderedType) :
sig
include module type of Map.Make(O)
module React :
sig
val map :
?eq:('a -> 'a -> bool) Eliom_shared.Value.t ->
(O.t -> 'a Eliom_shared.React.S.t -> 'b) Eliom_shared.Value.t ->
'a t Eliom_shared.React.S.t -> 'b t Eliom_shared.React.S.t
end
end =
struct
module M = Map.Make(O)
include M
module ESV = Eliom_shared.Value
module ERS = Eliom_shared.React.S
module React =
struct
let map ?eq f s =
ERS.const @@
M.fold
(fun k v m -> M.add k (ESV.local f k (ERS.const v)) m)
(ESV.local @@ ERS.value s) M.empty
end
end
]
[%%client
module Make(O : Map.OrderedType) :
sig
include module type of Map.Make(O)
module React :
sig
val merge : 'a React.signal t -> 'a t React.signal
val map_s :
?eq:('a -> 'a -> bool) ->
(O.t -> 'a React.signal -> 'b React.signal) ->
'a t React.signal -> 'b t React.signal
val map :
?eq:('a -> 'a -> bool) ->
(O.t -> 'a React.signal -> 'b) ->
'a t React.signal -> 'b t React.signal
end
end =
struct
include Map.Make(O)
module SSET = Set.Make(O)
module React =
struct
open React
open Shared_react
let merge m =
let changes =
fold
(fun k v l ->
let e = S.changes v |> E.map (fun x -> (k, x)) in
e :: l)
m [] |>
E.merge (fun l e -> e :: l) [] in
let init =
S.map ~eq:(==)
(fun l -> List.fold_left (fun m (k, v) -> add k v m) empty l) @@
S.merge ~eq:(==) (fun l x -> x :: l) [] @@
fold (fun k v l -> S.Pair.pair (S.const k) (S.keep_value v) :: l)
m []
in
S.space_safe_switch ~eq:(==) @@
S.map ~eq:(==)
(fun init ->
S.fold ~eq:(==)
(fun m l -> List.fold_left (fun m (k, v) -> add k v m) m l)
init
changes) @@
init
let keys m = fold (fun k _ l -> k :: l) m []
let map_s ?eq f m =
let key_changes =
S.diff
(fun m2 m1 ->
let b1 = SSET.of_list @@ keys m1 in
let b2 = SSET.of_list @@ keys m2 in
let deleted = SSET.elements @@ SSET.diff b1 b2 in
let added = SSET.elements @@ SSET.diff b2 b1 in
(added, deleted)) @@
m in
let mk k =
f k @@
S.space_safe_switch ?eq @@
S.map ~eq:(==)
(fun init ->
S.fmap ?eq
(fun m -> try Some (find k m) with Not_found -> None)
(find k init)
m) @@
S.keep_value m in
let init =
S.map ~eq:(==)
(fun m -> fold (fun k v m -> add k (mk k) m) m empty) @@
S.keep_value m
in
S.space_safe_switch ~eq:(==) @@
S.map ~eq:(==) merge @@
S.space_safe_switch ~eq:(==) @@
S.map
(fun init ->
S.fold ~eq:(==)
(fun m (added, deleted) ->
List.iter (fun k -> S.stop ~strong:true @@ find k m) deleted;
let m = List.fold_left (fun m k -> remove k m) m deleted in
let m = List.fold_left (fun m k -> add k (mk k) m) m added in
m)
init
key_changes)
init
let map ?eq f m =
let key_changes =
S.diff
(fun m2 m1 ->
let b1 = SSET.of_list @@ keys m1 in
let b2 = SSET.of_list @@ keys m2 in
let deleted = SSET.elements @@ SSET.diff b1 b2 in
let added = SSET.elements @@ SSET.diff b2 b1 in
(added, deleted)) @@
m in
let mk k =
let m =
S.space_safe_switch ?eq @@
S.map ~eq:(==)
(fun init ->
S.fmap ?eq
(fun m -> try Some (find k m) with Not_found -> None)
(find k init)
m) @@
S.keep_value m
in
(f k m, m) in
let signal init =
S.fold ~eq:(==)
(fun (m, m_) (added, deleted) ->
List.iter
(fun k ->
try S.stop ~strong:true @@ snd @@ find k m; with Not_found -> ())
deleted;
let m = List.fold_left (fun m k -> remove k m) m deleted in
let m_ = List.fold_left (fun m k -> remove k m) m_ deleted in
let added = List.map (fun k -> (k, mk k)) added in
let m = List.fold_left (fun m (k, v) -> add k v m) m added in
let m_ = List.fold_left (fun m (k, (v, _)) -> add k v m) m_ added in
(m, m_))
(init, map fst init)
key_changes
in
S.map ~eq:(==) snd @@
S.space_safe_switch ~eq:(==) @@
S.map ~eq:(==) signal @@
S.map ~eq:(==) (fun m -> fold (fun k v m -> add k (mk k) m) m empty) @@
S.keep_value m
end
end
]