PROOF.bend

bend-kit-collections@0.1.4.1 · 4,125 lines · 284 definitions

1import Base
2import bend-mathlib@0.7.4.0/nat.bend as MNat
3import bend-mathlib@0.7.4.0/bool.bend as MBool
4import bend-kit-collections@0.1.4.1/LAWS.bend as Laws
5import bend-kit-collections@0.1.4.1/omap.bend as O
6import bend-kit-collections@0.1.4.1/hmap.bend as M
7import bend-kit-collections@0.1.4.1/nat_order.bend as Ord
8import bend-kit-collections@0.1.4.1/order.bend as Order
9import bend-kit-lemmas@0.1.1.0/lemmas.bend as Lemmas
10
11def Laws.omap_keys_ascending_puts():
12  {==}
13
14def Laws.omap_size_del():
15  {==}
16
17def Laws.omap_get_after_rotations():
18  {==}
19
20def Laws.omap_keys_del_root():
21  {==}
22
23def Laws.omap_get_put():
24  {==}
25
26def Laws.omap_get_put_replace():
27  {==}
28
29def Laws.omap_get_put_other():
30  {==}
31
32def Laws.omap_get_missing():
33  {==}
34
35def Laws.omap_keys_sorted():
36  {==}
37
38def Laws.omap_size_replace():
39  {==}
40
41def Laws.omap_get_del():
42  {==}
43
44def Laws.omap_get_del_other():
45  {==}
46
47def Laws.omap_keys_del():
48  {==}
49
50def Laws.omap_string_keys():
51  {==}
52
53def Laws.oset_to_list():
54  {==}
55
56def Laws.oset_has_del():
57  {==}
58
59def Laws.vec_from_list():
60  {==}
61
62def Laws.vec_get():
63  {==}
64
65def Laws.vec_get_past_len():
66  {==}
67
68def Laws.vec_set():
69  {==}
70
71def Laws.vec_pop():
72  {==}
73
74def Laws.vec_pop_empty():
75  {==}
76
77def Laws.vec_pop_to_list():
78  {==}
79
80def Laws.deque_ends():
81  {==}
82
83def Laws.heap_sort():
84  {==}
85
86def c4.a(
87  +a: Bool, +b: Bool, +c: Bool, +d: Bool,
88  e: {Bool.and(Bool.and(Bool.and(a, b), c), d) == True{} : Bool}
89) -> {a == True{} : Bool}:
90  MBool.eq_true_of_and_left(a, b, MBool.eq_true_of_and_left(Bool.and(a, b), c, MBool.eq_true_of_and_left(Bool.and(Bool.and(a, b), c), d, e)))
91
92def c4.b(
93  +a: Bool, +b: Bool, +c: Bool, +d: Bool,
94  e: {Bool.and(Bool.and(Bool.and(a, b), c), d) == True{} : Bool}
95) -> {b == True{} : Bool}:
96  MBool.eq_true_of_and_right(a, b, MBool.eq_true_of_and_left(Bool.and(a, b), c, MBool.eq_true_of_and_left(Bool.and(Bool.and(a, b), c), d, e)))
97
98def c4.c(
99  +a: Bool, +b: Bool, +c: Bool, +d: Bool,
100  e: {Bool.and(Bool.and(Bool.and(a, b), c), d) == True{} : Bool}
101) -> {c == True{} : Bool}:
102  MBool.eq_true_of_and_right(Bool.and(a, b), c, MBool.eq_true_of_and_left(Bool.and(Bool.and(a, b), c), d, e))
103
104def c4.d(
105  +a: Bool, +b: Bool, +c: Bool, +d: Bool,
106  e: {Bool.and(Bool.and(Bool.and(a, b), c), d) == True{} : Bool}
107) -> {d == True{} : Bool}:
108  MBool.eq_true_of_and_right(Bool.and(Bool.and(a, b), c), d, e)
109
110def c4.i(
111  +a: Bool, +b: Bool, +c: Bool, +d: Bool, ea: {a == True{} : Bool},
112  eb: {b == True{} : Bool}, ec: {c == True{} : Bool}, ed: {d == True{} : Bool}
113) -> {Bool.and(Bool.and(Bool.and(a, b), c), d) == True{} : Bool}:
114  MBool.and_eq_true(Bool.and(Bool.and(a, b), c), d, MBool.and_eq_true(Bool.and(a, b), c, MBool.and_eq_true(a, b, ea, eb), ec), ed)
115
116
117def c3.a(+a: Bool, +b: Bool, +c: Bool, e: {Bool.and(Bool.and(a, b), c) == True{} : Bool}) -> {a == True{} : Bool}:
118  MBool.eq_true_of_and_left(a, b, MBool.eq_true_of_and_left(Bool.and(a, b), c, e))
119
120def c3.b(+a: Bool, +b: Bool, +c: Bool, e: {Bool.and(Bool.and(a, b), c) == True{} : Bool}) -> {b == True{} : Bool}:
121  MBool.eq_true_of_and_right(a, b, MBool.eq_true_of_and_left(Bool.and(a, b), c, e))
122
123def c3.c(+a: Bool, +b: Bool, +c: Bool, e: {Bool.and(Bool.and(a, b), c) == True{} : Bool}) -> {c == True{} : Bool}:
124  MBool.eq_true_of_and_right(Bool.and(a, b), c, e)
125
126def c3.i(+a: Bool, +b: Bool, +c: Bool, ea: {a == True{} : Bool}, eb: {b == True{} : Bool}, ec: {c == True{} : Bool})
127  -> {Bool.and(Bool.and(a, b), c) == True{} : Bool}:
128  MBool.and_eq_true(Bool.and(a, b), c, MBool.and_eq_true(a, b, ea, eb), ec)
129
130def Laws.omap_new_searchtree(K, V, cmp):
131  {==}
132
133def head(-K: Data, xs: List<&2, K>) -> Maybe<&2, K>:
134  match xs:
135    case Nil{}:
136      None{}
137    case Con{h, t}:
138      Some{h}
139
140# The list is sorted and its first element lies above lb.
141def sfrom(~K: Data, ~cmp: K -> K -> Cmp, lb: Maybe<&2, K>, xs: List<&2, K>) -> Bool:
142  match lb:
143    case None{}:
144      Laws.sorted(~K, ~cmp, xs)
145    case Some{b}:
146      Laws.sorted.go(~K, ~cmp, xs, b)
147
148# lb lies below ub, when both exist.
149def lt_m(~K: Data, ~cmp: K -> K -> Cmp, +lb: Maybe<&2, K>, ub: Maybe<&2, K>) -> Bool:
150  match ub:
151    case None{}:
152      True{}
153    case Some{u}:
154      Laws.above(~K, ~cmp, lb, u)
155
156def lt_m.some(
157  ~K: Data, ~cmp: K -> K -> Cmp, ub: Maybe<&2, K>, +k: K,
158  e: {Laws.below(~K, ~cmp, ub, k) == True{} : Bool}
159) -> {lt_m(~K, ~cmp, Some{k}, ub) == True{} : Bool}:
160  match ub:
161    case None{}:
162      {==}
163    case Some{u}:
164      e
165
166def sfrom.base(
167  ~K: Data, ~cmp: K -> K -> Cmp, lb: Maybe<&2, K>, acc: List<&2, K>,
168  lt: {lt_m(~K, ~cmp, lb, head(K, acc)) == True{} : Bool},
169  sa: {Laws.sorted(~K, ~cmp, acc) == True{} : Bool}
170) -> {sfrom(~K, ~cmp, lb, acc) == True{} : Bool}:
171  match lb acc:
172    case None{} _:
173      sa
174    case Some{b} Nil{}:
175      {==}
176    case Some{+b} Con{+h, t}:
177      MBool.and_eq_true(Cmp.is_lt(cmp(b, h)), Laws.sorted.go(~K, ~cmp, t, h), lt, sa)
178
179def keys_sorted.go(
180  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, t: O.OMap<K, V>, +lb: Maybe<&2, K>,
181  +acc: List<&2, K>,
182  +bt: {Laws.bounded(~K, ~V, ~cmp, t, lb, head(K, acc)) == True{} : Bool},
183  lt: {lt_m(~K, ~cmp, lb, head(K, acc)) == True{} : Bool},
184  sa: {Laws.sorted(~K, ~cmp, acc) == True{} : Bool}
185) -> {sfrom(~K, ~cmp, lb, O.OMap.keys.go(K, V, t, acc)) == True{} : Bool}:
186  match t:
187    case O.OTip{}:
188      sfrom.base(~K, ~cmp, lb, acc, lt, sa)
189    case O.OBin{s, +k, v, +lo, +hi}:
190      +A = Laws.above(~K, ~cmp, lb, k)
191      +B = Laws.below(~K, ~cmp, head(K, acc), k)
192      +L = Laws.bounded(~K, ~V, ~cmp, lo, lb, Some{k})
193      +H = Laws.bounded(~K, ~V, ~cmp, hi, Some{k}, head(K, acc))
194      ih = keys_sorted.go(~K, ~V, ~cmp, hi, Some{k}, acc, c4.d(A, B, L, H, bt),
195        lt_m.some(~K, ~cmp, head(K, acc), k, c4.b(A, B, L, H, bt)), sa)
196      keys_sorted.go(~K, ~V, ~cmp, lo, lb, k <> O.OMap.keys.go(K, V, hi, acc),
197        c4.c(A, B, L, H, bt), c4.a(A, B, L, H, bt), ih)
198
199def Laws.omap_searchtree_keys_sorted(K, V, cmp, m, tree):
200  keys_sorted.go(~K, ~V, ~cmp, m, None{}, Nil{}, tree, {==}, {==})
201
202def Trans(~K: Data, ~cmp: K -> K -> Cmp) -> Type:
203  @x: K -> @y: K -> @z: K -> {cmp(x, y) == LT{} : Cmp} -> {cmp(y, z) == LT{} : Cmp} -> {cmp(x, z) == LT{} : Cmp}
204
205def Flip(~K: Data, ~cmp: K -> K -> Cmp) -> Type:
206  @x: K -> @y: K -> {cmp(y, x) == Laws.flip(cmp(x, y)) : Cmp}
207
208def Refl(~K: Data, ~cmp: K -> K -> Cmp) -> Type:
209  @x: K -> {cmp(x, x) == EQ{} : Cmp}
210
211def Eq(~K: Data, ~cmp: K -> K -> Cmp) -> Type:
212  @x: K -> @y: K -> {cmp(x, y) == EQ{} : Cmp} -> {x == y : K}
213
214def lt_of(c: Cmp, e: {Cmp.is_lt(c) == True{} : Bool}) -> {c == LT{} : Cmp}:
215  match c:
216    case LT{}:
217      {==}
218    case EQ{}:
219      Empty.absurd({EQ{} == LT{} : Cmp}, MBool.false_ne_true()(e))
220    case GT{}:
221      Empty.absurd({GT{} == LT{} : Cmp}, MBool.false_ne_true()(e))
222
223def lt_true(-c: Cmp, e: {c == LT{} : Cmp}) -> {Cmp.is_lt(c) == True{} : Bool}:
224  Equal.cong(Cmp, Bool, x => Cmp.is_lt(x), c, LT{}, e)
225
226def gt_flip(
227  ~K: Data, ~cmp: K -> K -> Cmp, ~flip: Flip(~K, ~cmp), +x: K, +y: K,
228  e: {cmp(x, y) == GT{} : Cmp}
229) -> {cmp(y, x) == LT{} : Cmp}:
230  Equal.trans(Cmp, cmp(y, x), Laws.flip(cmp(x, y)), LT{}, flip(x, y),
231    Equal.cong(Cmp, Cmp, c => Laws.flip(c), cmp(x, y), GT{}, e))
232
233def lt_trans(
234  ~K: Data, ~cmp: K -> K -> Cmp, ~trans: Trans(~K, ~cmp), +x: K, +y: K, +z: K,
235  e1: {Cmp.is_lt(cmp(x, y)) == True{} : Bool},
236  e2: {Cmp.is_lt(cmp(y, z)) == True{} : Bool}
237) -> {Cmp.is_lt(cmp(x, z)) == True{} : Bool}:
238  lt_true(cmp(x, z), trans(x, y, z, lt_of(cmp(x, y), e1), lt_of(cmp(y, z), e2)))
239
240def above_trans(
241  ~K: Data, ~cmp: K -> K -> Cmp, ~trans: Trans(~K, ~cmp), lb: Maybe<&2, K>,
242  +k: K, +hk: K, ea: {Laws.above(~K, ~cmp, lb, k) == True{} : Bool},
243  e: {Cmp.is_lt(cmp(k, hk)) == True{} : Bool}
244) -> {Laws.above(~K, ~cmp, lb, hk) == True{} : Bool}:
245  match lb:
246    case None{}:
247      {==}
248    case Some{+b}:
249      lt_trans(~K, ~cmp, ~trans, b, k, hk, ea, e)
250
251def below_trans(
252  ~K: Data, ~cmp: K -> K -> Cmp, ~trans: Trans(~K, ~cmp), ub: Maybe<&2, K>,
253  +k: K, +hk: K, e: {Cmp.is_lt(cmp(k, hk)) == True{} : Bool},
254  eb: {Laws.below(~K, ~cmp, ub, hk) == True{} : Bool}
255) -> {Laws.below(~K, ~cmp, ub, k) == True{} : Bool}:
256  match ub:
257    case None{}:
258      {==}
259    case Some{+u}:
260      lt_trans(~K, ~cmp, ~trans, k, hk, u, e, eb)
261
262# Projections and introduction for bounded on one node.
263def bn.a(
264  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, +lb: Maybe<&2, K>, +ub: Maybe<&2, K>,
265  +k: K, -v: V, +lo: O.OMap<K, V>, +hi: O.OMap<K, V>,
266  e: {Laws.bounded(~K, ~V, ~cmp, O.OBin{0, k, v, lo, hi}, lb, ub) == True{} : Bool}
267) -> {Laws.above(~K, ~cmp, lb, k) == True{} : Bool}:
268  c4.a(Laws.above(~K, ~cmp, lb, k), Laws.below(~K, ~cmp, ub, k),
269    Laws.bounded(~K, ~V, ~cmp, lo, lb, Some{k}),
270    Laws.bounded(~K, ~V, ~cmp, hi, Some{k}, ub), e)
271
272def bn.b(
273  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, +lb: Maybe<&2, K>, +ub: Maybe<&2, K>,
274  +k: K, -v: V, +lo: O.OMap<K, V>, +hi: O.OMap<K, V>,
275  e: {Laws.bounded(~K, ~V, ~cmp, O.OBin{0, k, v, lo, hi}, lb, ub) == True{} : Bool}
276) -> {Laws.below(~K, ~cmp, ub, k) == True{} : Bool}:
277  c4.b(Laws.above(~K, ~cmp, lb, k), Laws.below(~K, ~cmp, ub, k),
278    Laws.bounded(~K, ~V, ~cmp, lo, lb, Some{k}),
279    Laws.bounded(~K, ~V, ~cmp, hi, Some{k}, ub), e)
280
281def bn.l(
282  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, +lb: Maybe<&2, K>, +ub: Maybe<&2, K>,
283  +k: K, -v: V, +lo: O.OMap<K, V>, +hi: O.OMap<K, V>,
284  e: {Laws.bounded(~K, ~V, ~cmp, O.OBin{0, k, v, lo, hi}, lb, ub) == True{} : Bool}
285) -> {Laws.bounded(~K, ~V, ~cmp, lo, lb, Some{k}) == True{} : Bool}:
286  c4.c(Laws.above(~K, ~cmp, lb, k), Laws.below(~K, ~cmp, ub, k),
287    Laws.bounded(~K, ~V, ~cmp, lo, lb, Some{k}),
288    Laws.bounded(~K, ~V, ~cmp, hi, Some{k}, ub), e)
289
290def bn.h(
291  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, +lb: Maybe<&2, K>, +ub: Maybe<&2, K>,
292  +k: K, -v: V, +lo: O.OMap<K, V>, +hi: O.OMap<K, V>,
293  e: {Laws.bounded(~K, ~V, ~cmp, O.OBin{0, k, v, lo, hi}, lb, ub) == True{} : Bool}
294) -> {Laws.bounded(~K, ~V, ~cmp, hi, Some{k}, ub) == True{} : Bool}:
295  c4.d(Laws.above(~K, ~cmp, lb, k), Laws.below(~K, ~cmp, ub, k),
296    Laws.bounded(~K, ~V, ~cmp, lo, lb, Some{k}),
297    Laws.bounded(~K, ~V, ~cmp, hi, Some{k}, ub), e)
298
299def bn.i(
300  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, +lb: Maybe<&2, K>, +ub: Maybe<&2, K>,
301  +k: K, -v: V, +lo: O.OMap<K, V>, +hi: O.OMap<K, V>,
302  ea: {Laws.above(~K, ~cmp, lb, k) == True{} : Bool},
303  eb: {Laws.below(~K, ~cmp, ub, k) == True{} : Bool},
304  el: {Laws.bounded(~K, ~V, ~cmp, lo, lb, Some{k}) == True{} : Bool},
305  eh: {Laws.bounded(~K, ~V, ~cmp, hi, Some{k}, ub) == True{} : Bool}
306) -> {Laws.bounded(~K, ~V, ~cmp, O.OBin{0, k, v, lo, hi}, lb, ub) == True{} : Bool}:
307  c4.i(Laws.above(~K, ~cmp, lb, k), Laws.below(~K, ~cmp, ub, k),
308    Laws.bounded(~K, ~V, ~cmp, lo, lb, Some{k}),
309    Laws.bounded(~K, ~V, ~cmp, hi, Some{k}, ub), ea, eb, el, eh)
310
311def rot_lo.single.bnd(
312  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~trans: Trans(~K, ~cmp),
313  +lb: Maybe<&2, K>, +ub: Maybe<&2, K>, +k: K, +v: V, +lo: O.OMap<K, V>,
314  +hk: K, +hv: V, +hl: O.OMap<K, V>, +hh: O.OMap<K, V>,
315  +ea: {Laws.above(~K, ~cmp, lb, k) == True{} : Bool},
316  el: {Laws.bounded(~K, ~V, ~cmp, lo, lb, Some{k}) == True{} : Bool},
317  +eh: {Laws.bounded(~K, ~V, ~cmp, O.OBin{0, hk, hv, hl, hh}, Some{k}, ub) == True{} : Bool}
318) -> {Laws.bounded(~K, ~V, ~cmp,
319       O.OMap.bin(K, V, hk, hv, O.OMap.bin(K, V, k, v, lo, hl), hh), lb, ub) == True{} : Bool}:
320  +h_a = bn.a(~K, ~V, ~cmp, Some{k}, ub, hk, hv, hl, hh, eh)
321  bn.i(~K, ~V, ~cmp, lb, ub, hk, hv, O.OMap.bin(K, V, k, v, lo, hl), hh,
322    above_trans(~K, ~cmp, ~trans, lb, k, hk, ea, h_a),
323    bn.b(~K, ~V, ~cmp, Some{k}, ub, hk, hv, hl, hh, eh),
324    bn.i(~K, ~V, ~cmp, lb, Some{hk}, k, v, lo, hl, ea, h_a, el,
325      bn.l(~K, ~V, ~cmp, Some{k}, ub, hk, hv, hl, hh, eh)),
326    bn.h(~K, ~V, ~cmp, Some{k}, ub, hk, hv, hl, hh, eh))
327
328def rot_lo.double.bnd(
329  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~trans: Trans(~K, ~cmp),
330  hl: O.OMap<K, V>, +lb: Maybe<&2, K>, +ub: Maybe<&2, K>, +k: K, +v: V,
331  +lo: O.OMap<K, V>, +hk: K, +hv: V, +hh: O.OMap<K, V>,
332  +ea: {Laws.above(~K, ~cmp, lb, k) == True{} : Bool},
333  el: {Laws.bounded(~K, ~V, ~cmp, lo, lb, Some{k}) == True{} : Bool},
334  +eh: {Laws.bounded(~K, ~V, ~cmp, O.OBin{0, hk, hv, hl, hh}, Some{k}, ub) == True{} : Bool}
335) -> {Laws.bounded(~K, ~V, ~cmp,
336       O.OMap.rot_lo.double(K, V, k, v, lo, hk, hv, hl, hh), lb, ub) == True{} : Bool}:
337  match hl:
338    case O.OTip{}:
339      rot_lo.single.bnd(~K, ~V, ~cmp, ~trans, lb, ub, k, v, lo, hk, hv, O.OTip{}, hh,
340        ea, el, eh)
341    case O.OBin{s, +mk, +mv, +ml, +mh}:
342      +hl = {O.OBin{0, mk, mv, ml, mh} : O.OMap<K, V>}
343      +h_b = bn.b(~K, ~V, ~cmp, Some{k}, ub, hk, hv, hl, hh, eh)
344      +h_l = bn.l(~K, ~V, ~cmp, Some{k}, ub, hk, hv, hl, hh, eh)
345      +m_a = bn.a(~K, ~V, ~cmp, Some{k}, Some{hk}, mk, mv, ml, mh, h_l)
346      +m_b = bn.b(~K, ~V, ~cmp, Some{k}, Some{hk}, mk, mv, ml, mh, h_l)
347      bn.i(~K, ~V, ~cmp, lb, ub, mk, mv, O.OMap.bin(K, V, k, v, lo, ml),
348        O.OMap.bin(K, V, hk, hv, mh, hh),
349        above_trans(~K, ~cmp, ~trans, lb, k, mk, ea, m_a),
350        below_trans(~K, ~cmp, ~trans, ub, mk, hk, m_b, h_b),
351        bn.i(~K, ~V, ~cmp, lb, Some{mk}, k, v, lo, ml, ea, m_a, el,
352          bn.l(~K, ~V, ~cmp, Some{k}, Some{hk}, mk, mv, ml, mh, h_l)),
353        bn.i(~K, ~V, ~cmp, Some{mk}, ub, hk, hv, mh, hh, m_b, h_b,
354          bn.h(~K, ~V, ~cmp, Some{k}, Some{hk}, mk, mv, ml, mh, h_l),
355          bn.h(~K, ~V, ~cmp, Some{k}, ub, hk, hv, hl, hh, eh)))
356
357def rot_lo.pick.bnd(
358  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~trans: Trans(~K, ~cmp),
359  single: Bool, +lb: Maybe<&2, K>, +ub: Maybe<&2, K>, +k: K, +v: V,
360  +lo: O.OMap<K, V>, +hk: K, +hv: V, +hl: O.OMap<K, V>, +hh: O.OMap<K, V>,
361  +ea: {Laws.above(~K, ~cmp, lb, k) == True{} : Bool},
362  el: {Laws.bounded(~K, ~V, ~cmp, lo, lb, Some{k}) == True{} : Bool},
363  +eh: {Laws.bounded(~K, ~V, ~cmp, O.OBin{0, hk, hv, hl, hh}, Some{k}, ub) == True{} : Bool}
364) -> {Laws.bounded(~K, ~V, ~cmp,
365       O.OMap.rot_lo.pick(K, V, single, k, v, lo, hk, hv, hl, hh), lb, ub) == True{} : Bool}:
366  match single:
367    case True{}:
368      rot_lo.single.bnd(~K, ~V, ~cmp, ~trans, lb, ub, k, v, lo, hk, hv, hl, hh, ea, el, eh)
369    case False{}:
370      rot_lo.double.bnd(~K, ~V, ~cmp, ~trans, hl, lb, ub, k, v, lo, hk, hv, hh, ea, el, eh)
371
372def rot_lo.bnd(
373  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~trans: Trans(~K, ~cmp),
374  hi: O.OMap<K, V>, +lb: Maybe<&2, K>, +ub: Maybe<&2, K>, +k: K, +v: V,
375  +lo: O.OMap<K, V>,
376  +ea: {Laws.above(~K, ~cmp, lb, k) == True{} : Bool},
377  eb: {Laws.below(~K, ~cmp, ub, k) == True{} : Bool},
378  el: {Laws.bounded(~K, ~V, ~cmp, lo, lb, Some{k}) == True{} : Bool},
379  +eh: {Laws.bounded(~K, ~V, ~cmp, hi, Some{k}, ub) == True{} : Bool}
380) -> {Laws.bounded(~K, ~V, ~cmp, O.OMap.rot_lo(K, V, k, v, lo, hi), lb, ub) == True{} : Bool}:
381  match hi:
382    case O.OTip{}:
383      bn.i(~K, ~V, ~cmp, lb, ub, k, v, lo, O.OTip{}, ea, eb, el, eh)
384    case O.OBin{s, +hk, +hv, +hl, +hh}:
385      rot_lo.pick.bnd(~K, ~V, ~cmp, ~trans,
386        U32.is_lt((O.OMap.size(K, V, hl) + 1 : U32),
387          (2 * (O.OMap.size(K, V, hh) + 1) : U32)),
388        lb, ub, k, v, lo, hk, hv, hl, hh, ea, el, eh)
389
390def rot_hi.single.bnd(
391  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~trans: Trans(~K, ~cmp),
392  +lb: Maybe<&2, K>, +ub: Maybe<&2, K>, +k: K, +v: V, +lk: K, +lv: V,
393  +ll: O.OMap<K, V>, +lh: O.OMap<K, V>, +hi: O.OMap<K, V>,
394  +eb: {Laws.below(~K, ~cmp, ub, k) == True{} : Bool},
395  +el: {Laws.bounded(~K, ~V, ~cmp, O.OBin{0, lk, lv, ll, lh}, lb, Some{k}) == True{} : Bool},
396  eh: {Laws.bounded(~K, ~V, ~cmp, hi, Some{k}, ub) == True{} : Bool}
397) -> {Laws.bounded(~K, ~V, ~cmp,
398       O.OMap.bin(K, V, lk, lv, ll, O.OMap.bin(K, V, k, v, lh, hi)), lb, ub) == True{} : Bool}:
399  +l_b = bn.b(~K, ~V, ~cmp, lb, Some{k}, lk, lv, ll, lh, el)
400  bn.i(~K, ~V, ~cmp, lb, ub, lk, lv, ll, O.OMap.bin(K, V, k, v, lh, hi),
401    bn.a(~K, ~V, ~cmp, lb, Some{k}, lk, lv, ll, lh, el),
402    below_trans(~K, ~cmp, ~trans, ub, lk, k, l_b, eb),
403    bn.l(~K, ~V, ~cmp, lb, Some{k}, lk, lv, ll, lh, el),
404    bn.i(~K, ~V, ~cmp, Some{lk}, ub, k, v, lh, hi, l_b, eb,
405      bn.h(~K, ~V, ~cmp, lb, Some{k}, lk, lv, ll, lh, el), eh))
406
407def rot_hi.double.bnd(
408  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~trans: Trans(~K, ~cmp),
409  lh: O.OMap<K, V>, +lb: Maybe<&2, K>, +ub: Maybe<&2, K>, +k: K, +v: V,
410  +lk: K, +lv: V, +ll: O.OMap<K, V>, +hi: O.OMap<K, V>,
411  +eb: {Laws.below(~K, ~cmp, ub, k) == True{} : Bool},
412  +el: {Laws.bounded(~K, ~V, ~cmp, O.OBin{0, lk, lv, ll, lh}, lb, Some{k}) == True{} : Bool},
413  eh: {Laws.bounded(~K, ~V, ~cmp, hi, Some{k}, ub) == True{} : Bool}
414) -> {Laws.bounded(~K, ~V, ~cmp,
415       O.OMap.rot_hi.double(K, V, k, v, lk, lv, ll, lh, hi), lb, ub) == True{} : Bool}:
416  match lh:
417    case O.OTip{}:
418      rot_hi.single.bnd(~K, ~V, ~cmp, ~trans, lb, ub, k, v, lk, lv, ll, O.OTip{}, hi,
419        eb, el, eh)
420    case O.OBin{s, +mk, +mv, +ml, +mh}:
421      +lh = {O.OBin{0, mk, mv, ml, mh} : O.OMap<K, V>}
422      +l_a = bn.a(~K, ~V, ~cmp, lb, Some{k}, lk, lv, ll, lh, el)
423      +l_h = bn.h(~K, ~V, ~cmp, lb, Some{k}, lk, lv, ll, lh, el)
424      +m_a = bn.a(~K, ~V, ~cmp, Some{lk}, Some{k}, mk, mv, ml, mh, l_h)
425      +m_b = bn.b(~K, ~V, ~cmp, Some{lk}, Some{k}, mk, mv, ml, mh, l_h)
426      bn.i(~K, ~V, ~cmp, lb, ub, mk, mv, O.OMap.bin(K, V, lk, lv, ll, ml),
427        O.OMap.bin(K, V, k, v, mh, hi),
428        above_trans(~K, ~cmp, ~trans, lb, lk, mk, l_a, m_a),
429        below_trans(~K, ~cmp, ~trans, ub, mk, k, m_b, eb),
430        bn.i(~K, ~V, ~cmp, lb, Some{mk}, lk, lv, ll, ml, l_a, m_a,
431          bn.l(~K, ~V, ~cmp, lb, Some{k}, lk, lv, ll, lh, el),
432          bn.l(~K, ~V, ~cmp, Some{lk}, Some{k}, mk, mv, ml, mh, l_h)),
433        bn.i(~K, ~V, ~cmp, Some{mk}, ub, k, v, mh, hi, m_b, eb,
434          bn.h(~K, ~V, ~cmp, Some{lk}, Some{k}, mk, mv, ml, mh, l_h), eh))
435
436def rot_hi.pick.bnd(
437  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~trans: Trans(~K, ~cmp),
438  single: Bool, +lb: Maybe<&2, K>, +ub: Maybe<&2, K>, +k: K, +v: V,
439  +lk: K, +lv: V, +ll: O.OMap<K, V>, +lh: O.OMap<K, V>, +hi: O.OMap<K, V>,
440  +eb: {Laws.below(~K, ~cmp, ub, k) == True{} : Bool},
441  +el: {Laws.bounded(~K, ~V, ~cmp, O.OBin{0, lk, lv, ll, lh}, lb, Some{k}) == True{} : Bool},
442  eh: {Laws.bounded(~K, ~V, ~cmp, hi, Some{k}, ub) == True{} : Bool}
443) -> {Laws.bounded(~K, ~V, ~cmp,
444       O.OMap.rot_hi.pick(K, V, single, k, v, lk, lv, ll, lh, hi), lb, ub) == True{} : Bool}:
445  match single:
446    case True{}:
447      rot_hi.single.bnd(~K, ~V, ~cmp, ~trans, lb, ub, k, v, lk, lv, ll, lh, hi, eb, el, eh)
448    case False{}:
449      rot_hi.double.bnd(~K, ~V, ~cmp, ~trans, lh, lb, ub, k, v, lk, lv, ll, hi, eb, el, eh)
450
451def rot_hi.bnd(
452  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~trans: Trans(~K, ~cmp),
453  lo: O.OMap<K, V>, +lb: Maybe<&2, K>, +ub: Maybe<&2, K>, +k: K, +v: V,
454  +hi: O.OMap<K, V>,
455  ea: {Laws.above(~K, ~cmp, lb, k) == True{} : Bool},
456  +eb: {Laws.below(~K, ~cmp, ub, k) == True{} : Bool},
457  +el: {Laws.bounded(~K, ~V, ~cmp, lo, lb, Some{k}) == True{} : Bool},
458  eh: {Laws.bounded(~K, ~V, ~cmp, hi, Some{k}, ub) == True{} : Bool}
459) -> {Laws.bounded(~K, ~V, ~cmp, O.OMap.rot_hi(K, V, k, v, lo, hi), lb, ub) == True{} : Bool}:
460  match lo:
461    case O.OTip{}:
462      bn.i(~K, ~V, ~cmp, lb, ub, k, v, O.OTip{}, hi, ea, eb, el, eh)
463    case O.OBin{s, +lk, +lv, +ll, +lh}:
464      rot_hi.pick.bnd(~K, ~V, ~cmp, ~trans,
465        U32.is_lt((O.OMap.size(K, V, lh) + 1 : U32),
466          (2 * (O.OMap.size(K, V, ll) + 1) : U32)),
467        lb, ub, k, v, lk, lv, ll, lh, hi, eb, el, eh)
468
469def balance.if.bnd(
470  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~trans: Trans(~K, ~cmp),
471  heavy_hi: Bool, heavy_lo: Bool, +lb: Maybe<&2, K>, +ub: Maybe<&2, K>, +k: K,
472  +v: V, +lo: O.OMap<K, V>, +hi: O.OMap<K, V>,
473  +ea: {Laws.above(~K, ~cmp, lb, k) == True{} : Bool},
474  +eb: {Laws.below(~K, ~cmp, ub, k) == True{} : Bool},
475  +el: {Laws.bounded(~K, ~V, ~cmp, lo, lb, Some{k}) == True{} : Bool},
476  +eh: {Laws.bounded(~K, ~V, ~cmp, hi, Some{k}, ub) == True{} : Bool}
477) -> {Laws.bounded(~K, ~V, ~cmp,
478       O.OMap.balance.if(K, V, heavy_hi, heavy_lo, k, v, lo, hi), lb, ub) == True{} : Bool}:
479  match heavy_hi heavy_lo:
480    case True{} _:
481      rot_lo.bnd(~K, ~V, ~cmp, ~trans, hi, lb, ub, k, v, lo, ea, eb, el, eh)
482    case False{} True{}:
483      rot_hi.bnd(~K, ~V, ~cmp, ~trans, lo, lb, ub, k, v, hi, ea, eb, el, eh)
484    case False{} False{}:
485      bn.i(~K, ~V, ~cmp, lb, ub, k, v, lo, hi, ea, eb, el, eh)
486
487def balance.bnd(
488  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~trans: Trans(~K, ~cmp),
489  +lb: Maybe<&2, K>, +ub: Maybe<&2, K>, +k: K, +v: V, +lo: O.OMap<K, V>,
490  +hi: O.OMap<K, V>,
491  ea: {Laws.above(~K, ~cmp, lb, k) == True{} : Bool},
492  eb: {Laws.below(~K, ~cmp, ub, k) == True{} : Bool},
493  el: {Laws.bounded(~K, ~V, ~cmp, lo, lb, Some{k}) == True{} : Bool},
494  eh: {Laws.bounded(~K, ~V, ~cmp, hi, Some{k}, ub) == True{} : Bool}
495) -> {Laws.bounded(~K, ~V, ~cmp, O.OMap.balance(K, V, k, v, lo, hi), lb, ub) == True{} : Bool}:
496  +wl = (O.OMap.size(K, V, lo) + 1 : U32)
497  +wh = (O.OMap.size(K, V, hi) + 1 : U32)
498  balance.if.bnd(~K, ~V, ~cmp, ~trans, U32.is_gt(wh, (3 * wl : U32)),
499    U32.is_gt(wl, (3 * wh : U32)), lb, ub, k, v, lo, hi, ea, eb, el, eh)
500
501# Proves a goal about O.Cmp.case by one case per comparison result.
502def cmp.split(
503  -A: Type, -B: Type, -F: A -> B, -G: B, c: Cmp, -f1: Unit -> A,
504  -f2: Unit -> A, -f3: Unit -> A,
505  hl: {c == LT{} : Cmp} -> {F(f1(Unit{})) == G : B},
506  he: {c == EQ{} : Cmp} -> {F(f2(Unit{})) == G : B},
507  hg: {c == GT{} : Cmp} -> {F(f3(Unit{})) == G : B}
508) -> {F(O.Cmp.case(A, c, f1, f2, f3)) == G : B}:
509  match c:
510    case LT{}:
511      hl({==})
512    case EQ{}:
513      he({==})
514    case GT{}:
515      hg({==})
516
517def put.bnd(
518  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~flip: Flip(~K, ~cmp),
519  ~trans: Trans(~K, ~cmp), t: O.OMap<K, V>, +lb: Maybe<&2, K>,
520  +ub: Maybe<&2, K>, +k: K, +v: V,
521  +bt: {Laws.bounded(~K, ~V, ~cmp, t, lb, ub) == True{} : Bool},
522  +ea: {Laws.above(~K, ~cmp, lb, k) == True{} : Bool},
523  +eb: {Laws.below(~K, ~cmp, ub, k) == True{} : Bool}
524) -> {Laws.bounded(~K, ~V, ~cmp, O.OMap.put(~K, ~V, ~cmp, t, k, v), lb, ub) == True{} : Bool}:
525  match t:
526    case O.OTip{}:
527      bn.i(~K, ~V, ~cmp, lb, ub, k, v, O.OTip{}, O.OTip{}, ea, eb, {==}, {==})
528    case O.OBin{+s, +key, +val, +lo, +hi}:
529      +b_a = bn.a(~K, ~V, ~cmp, lb, ub, key, val, lo, hi, bt)
530      +b_b = bn.b(~K, ~V, ~cmp, lb, ub, key, val, lo, hi, bt)
531      +b_l = bn.l(~K, ~V, ~cmp, lb, ub, key, val, lo, hi, bt)
532      +b_h = bn.h(~K, ~V, ~cmp, lb, ub, key, val, lo, hi, bt)
533      cmp.split(O.OMap<K, V>, Bool, x => Laws.bounded(~K, ~V, ~cmp, x, lb, ub), True{},
534        cmp(k, key),
535        u => O.OMap.balance(K, V, key, val, O.OMap.put(~K, ~V, ~cmp, lo, k, v), hi),
536        u => O.OBin{s, key, v, lo, hi},
537        u => O.OMap.balance(K, V, key, val, lo, O.OMap.put(~K, ~V, ~cmp, hi, k, v)),
538        e => balance.bnd(~K, ~V, ~cmp, ~trans, lb, ub, key, val,
539          O.OMap.put(~K, ~V, ~cmp, lo, k, v), hi, b_a, b_b,
540          put.bnd(~K, ~V, ~cmp, ~flip, ~trans, lo, lb, Some{key}, k, v, b_l, ea,
541            lt_true(cmp(k, key), e)),
542          b_h),
543        e => bt,
544        e => balance.bnd(~K, ~V, ~cmp, ~trans, lb, ub, key, val, lo,
545          O.OMap.put(~K, ~V, ~cmp, hi, k, v), b_a, b_b, b_l,
546          put.bnd(~K, ~V, ~cmp, ~flip, ~trans, hi, Some{key}, ub, k, v, b_h,
547            lt_true(cmp(key, k), gt_flip(~K, ~cmp, ~flip, k, key, e)), eb)))
548
549def Laws.omap_put_searchtree(K, V, cmp, refl, eq, flip, trans, m, tree, k, v):
550  put.bnd(~K, ~V, ~cmp, ~flip, ~trans, m, None{}, None{}, k, v, tree, {==}, {==})
551
552def rw(-A: Type, -P: A -> Type, -a: A, -b: A, e: {a == b : A}, p: P(b)) -> P(a):
553  %Equal.sym(A, a, b, e) : P(_)
554  p
555
556def split(
557  -P: Cmp -> Type, c: Cmp, hl: {c == LT{} : Cmp} -> P(LT{}),
558  he: {c == EQ{} : Cmp} -> P(EQ{}), hg: {c == GT{} : Cmp} -> P(GT{})
559) -> P(c):
560  match c:
561    case LT{}:
562      hl({==})
563    case EQ{}:
564      he({==})
565    case GT{}:
566      hg({==})
567
568def gt_of_lt(
569  ~K: Data, ~cmp: K -> K -> Cmp, ~flip: Flip(~K, ~cmp), +x: K, +y: K,
570  e: {cmp(x, y) == LT{} : Cmp}
571) -> {cmp(y, x) == GT{} : Cmp}:
572  Equal.trans(Cmp, cmp(y, x), Laws.flip(cmp(x, y)), GT{}, flip(x, y),
573    Equal.cong(Cmp, Cmp, c => Laws.flip(c), cmp(x, y), LT{}, e))
574
575# get on one node, with the comparison result as a parameter.
576def getc(
577  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, c: Cmp, +x: K, +val: V,
578  lo: O.OMap<K, V>, hi: O.OMap<K, V>
579) -> Maybe<&2, V>:
580  O.Cmp.case(Maybe<&2, V>, c,
581    u => O.OMap.get(~K, ~V, ~cmp, lo, x),
582    u => Some{val},
583    u => O.OMap.get(~K, ~V, ~cmp, hi, x))
584
585# get finds key k itself in a node keyed by k.
586def get.here(
587  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~refl: Refl(~K, ~cmp), +k: K, +v: V,
588  +lo: O.OMap<K, V>, +hi: O.OMap<K, V>
589) -> {O.OMap.get(~K, ~V, ~cmp, O.OBin{0, k, v, lo, hi}, k) == Some{v} : Maybe<&2, V>}:
590  rw(Cmp, c => {getc(~K, ~V, ~cmp, c, k, v, lo, hi) == Some{v} : Maybe<&2, V>},
591    cmp(k, k), EQ{}, refl(k), {==})
592
593# get on a node goes to lo when the comparison is LT.
594def get.lt(
595  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, +x: K, +k: K, +v: V,
596  +lo: O.OMap<K, V>, +hi: O.OMap<K, V>, e: {cmp(x, k) == LT{} : Cmp}
597) -> {O.OMap.get(~K, ~V, ~cmp, O.OBin{0, k, v, lo, hi}, x)
598      == O.OMap.get(~K, ~V, ~cmp, lo, x) : Maybe<&2, V>}:
599  rw(Cmp, c => {getc(~K, ~V, ~cmp, c, x, v, lo, hi)
600      == O.OMap.get(~K, ~V, ~cmp, lo, x) : Maybe<&2, V>},
601    cmp(x, k), LT{}, e, {==})
602
603# get on a node goes to hi when the comparison is GT.
604def get.gt(
605  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, +x: K, +k: K, +v: V,
606  +lo: O.OMap<K, V>, +hi: O.OMap<K, V>, e: {cmp(x, k) == GT{} : Cmp}
607) -> {O.OMap.get(~K, ~V, ~cmp, O.OBin{0, k, v, lo, hi}, x)
608      == O.OMap.get(~K, ~V, ~cmp, hi, x) : Maybe<&2, V>}:
609  rw(Cmp, c => {getc(~K, ~V, ~cmp, c, x, v, lo, hi)
610      == O.OMap.get(~K, ~V, ~cmp, hi, x) : Maybe<&2, V>},
611    cmp(x, k), GT{}, e, {==})
612
613def rot_lo.single.get(
614  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~refl: Refl(~K, ~cmp), ~eq: Eq(~K, ~cmp),
615  ~flip: Flip(~K, ~cmp), ~trans: Trans(~K, ~cmp),
616  +x: K, +k: K, +v: V, +lo: O.OMap<K, V>, +hk: K,
617  +hv: V, +hl: O.OMap<K, V>, +hh: O.OMap<K, V>, +khk: {cmp(k, hk) == LT{} : Cmp}
618) -> {O.OMap.get(~K, ~V, ~cmp,
619       O.OMap.bin(K, V, hk, hv, O.OMap.bin(K, V, k, v, lo, hl), hh), x)
620      == O.OMap.get(~K, ~V, ~cmp, O.OBin{0, k, v, lo, O.OBin{0, hk, hv, hl, hh}}, x)
621      : Maybe<&2, V>}:
622  +inner = {O.OBin{0, k, v, lo, hl} : O.OMap<K, V>}
623  +lhs = {O.OBin{0, hk, hv, inner, hh} : O.OMap<K, V>}
624  split(c => {O.OMap.get(~K, ~V, ~cmp, lhs, x)
625      == getc(~K, ~V, ~cmp, c, x, v, lo, O.OBin{0, hk, hv, hl, hh}) : Maybe<&2, V>},
626    cmp(x, k),
627    +e => Equal.trans(Maybe<&2, V>, O.OMap.get(~K, ~V, ~cmp, lhs, x),
628      O.OMap.get(~K, ~V, ~cmp, inner, x), O.OMap.get(~K, ~V, ~cmp, lo, x),
629      get.lt(~K, ~V, ~cmp, x, hk, hv, inner, hh, trans(x, k, hk, e, khk)),
630      get.lt(~K, ~V, ~cmp, x, k, v, lo, hl, e)),
631    e => rw(K, y => {O.OMap.get(~K, ~V, ~cmp, lhs, y) == Some{v} : Maybe<&2, V>},
632      x, k, eq(x, k, e),
633      Equal.trans(Maybe<&2, V>, O.OMap.get(~K, ~V, ~cmp, lhs, k),
634        O.OMap.get(~K, ~V, ~cmp, inner, k), Some{v},
635        get.lt(~K, ~V, ~cmp, k, hk, hv, inner, hh, khk),
636        get.here(~K, ~V, ~cmp, ~refl, k, v, lo, hl))),
637    e => split(c => {getc(~K, ~V, ~cmp, c, x, hv, inner, hh)
638        == getc(~K, ~V, ~cmp, c, x, hv, hl, hh) : Maybe<&2, V>},
639      cmp(x, hk),
640      e2 => get.gt(~K, ~V, ~cmp, x, k, v, lo, hl, e),
641      e2 => {==},
642      e2 => {==}))
643
644def g(~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, t: O.OMap<K, V>, +x: K) -> Maybe<&2, V>:
645  O.OMap.get(~K, ~V, ~cmp, t, x)
646
647def mtr(
648  -V: Data, -a: Maybe<&2, V>, -b: Maybe<&2, V>, -c: Maybe<&2, V>,
649  e1: {a == b : Maybe<&2, V>}, e2: {b == c : Maybe<&2, V>}
650) -> {a == c : Maybe<&2, V>}:
651  Equal.trans(Maybe<&2, V>, a, b, c, e1, e2)
652
653def rot_lo.double.get2(
654  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~refl: Refl(~K, ~cmp), ~eq: Eq(~K, ~cmp),
655  ~flip: Flip(~K, ~cmp), ~trans: Trans(~K, ~cmp),
656  +x: K, +k: K, +v: V, +lo: O.OMap<K, V>, +hk: K, +hv: V, +mk: K, +mv: V,
657  +ml: O.OMap<K, V>, +mh: O.OMap<K, V>, +hh: O.OMap<K, V>,
658  +khm: {cmp(k, mk) == LT{} : Cmp}, +mhk: {cmp(mk, hk) == LT{} : Cmp}
659) -> {g(~K, ~V, ~cmp, O.OMap.bin(K, V, mk, mv, O.OMap.bin(K, V, k, v, lo, ml),
660        O.OMap.bin(K, V, hk, hv, mh, hh)), x)
661      == g(~K, ~V, ~cmp, O.OBin{0, k, v, lo, O.OBin{0, hk, hv, O.OBin{0, mk, mv, ml, mh}, hh}}, x)
662      : Maybe<&2, V>}:
663  +a = {O.OBin{0, k, v, lo, ml} : O.OMap<K, V>}
664  +b = {O.OBin{0, hk, hv, mh, hh} : O.OMap<K, V>}
665  +l = {O.OBin{0, mk, mv, a, b} : O.OMap<K, V>}
666  +m = {O.OBin{0, mk, mv, ml, mh} : O.OMap<K, V>}
667  +r1 = {O.OBin{0, hk, hv, m, hh} : O.OMap<K, V>}
668  split(c => {g(~K, ~V, ~cmp, l, x) == getc(~K, ~V, ~cmp, c, x, v, lo, r1) : Maybe<&2, V>},
669    cmp(x, k),
670    +e => mtr(V, g(~K, ~V, ~cmp, l, x), g(~K, ~V, ~cmp, a, x), g(~K, ~V, ~cmp, lo, x),
671      get.lt(~K, ~V, ~cmp, x, mk, mv, a, b, trans(x, k, mk, e, khm)),
672      get.lt(~K, ~V, ~cmp, x, k, v, lo, ml, e)),
673    e => rw(K, y => {g(~K, ~V, ~cmp, l, y) == Some{v} : Maybe<&2, V>}, x, k, eq(x, k, e),
674      mtr(V, g(~K, ~V, ~cmp, l, k), g(~K, ~V, ~cmp, a, k), Some{v},
675        get.lt(~K, ~V, ~cmp, k, mk, mv, a, b, khm),
676        get.here(~K, ~V, ~cmp, ~refl, k, v, lo, ml))),
677    +e => split(c => {g(~K, ~V, ~cmp, l, x) == getc(~K, ~V, ~cmp, c, x, hv, m, hh) : Maybe<&2, V>},
678      cmp(x, hk),
679      +e2 => split(c => {getc(~K, ~V, ~cmp, c, x, mv, a, b)
680          == getc(~K, ~V, ~cmp, c, x, mv, ml, mh) : Maybe<&2, V>},
681        cmp(x, mk),
682        e3 => get.gt(~K, ~V, ~cmp, x, k, v, lo, ml, e),
683        e3 => {==},
684        e3 => get.lt(~K, ~V, ~cmp, x, hk, hv, mh, hh, e2)),
685      e2 => rw(K, y => {g(~K, ~V, ~cmp, l, y) == Some{hv} : Maybe<&2, V>}, x, hk, eq(x, hk, e2),
686        mtr(V, g(~K, ~V, ~cmp, l, hk), g(~K, ~V, ~cmp, b, hk), Some{hv},
687          get.gt(~K, ~V, ~cmp, hk, mk, mv, a, b, gt_of_lt(~K, ~cmp, ~flip, mk, hk, mhk)),
688          get.here(~K, ~V, ~cmp, ~refl, hk, hv, mh, hh))),
689      +e2 => mtr(V, g(~K, ~V, ~cmp, l, x), g(~K, ~V, ~cmp, b, x), g(~K, ~V, ~cmp, hh, x),
690        get.gt(~K, ~V, ~cmp, x, mk, mv, a, b,
691          gt_of_lt(~K, ~cmp, ~flip, mk, x,
692            trans(mk, hk, x, mhk, gt_flip(~K, ~cmp, ~flip, x, hk, e2)))),
693        get.gt(~K, ~V, ~cmp, x, hk, hv, mh, hh, e2))))
694
695def rot_lo.double.get(
696  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~refl: Refl(~K, ~cmp), ~eq: Eq(~K, ~cmp),
697  ~flip: Flip(~K, ~cmp), ~trans: Trans(~K, ~cmp),
698  hl: O.OMap<K, V>, +x: K, +k: K, +v: V, +lo: O.OMap<K, V>, +hk: K, +hv: V,
699  +hh: O.OMap<K, V>, +khk: {cmp(k, hk) == LT{} : Cmp},
700  +h_l: {Laws.bounded(~K, ~V, ~cmp, hl, Some{k}, Some{hk}) == True{} : Bool}
701) -> {g(~K, ~V, ~cmp, O.OMap.rot_lo.double(K, V, k, v, lo, hk, hv, hl, hh), x)
702      == g(~K, ~V, ~cmp, O.OBin{0, k, v, lo, O.OBin{0, hk, hv, hl, hh}}, x) : Maybe<&2, V>}:
703  match hl:
704    case O.OTip{}:
705      rot_lo.single.get(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans, x, k, v, lo, hk, hv,
706        O.OTip{}, hh, khk)
707    case O.OBin{s, +mk, +mv, +ml, +mh}:
708      rot_lo.double.get2(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans, x, k, v, lo, hk, hv,
709        mk, mv, ml, mh, hh,
710        lt_of(cmp(k, mk), bn.a(~K, ~V, ~cmp, Some{k}, Some{hk}, mk, mv, ml, mh, h_l)),
711        lt_of(cmp(mk, hk), bn.b(~K, ~V, ~cmp, Some{k}, Some{hk}, mk, mv, ml, mh, h_l)))
712
713def rot_lo.pick.get(
714  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~refl: Refl(~K, ~cmp), ~eq: Eq(~K, ~cmp),
715  ~flip: Flip(~K, ~cmp), ~trans: Trans(~K, ~cmp),
716  single: Bool, +x: K, +k: K, +v: V, +lo: O.OMap<K, V>, +hk: K, +hv: V,
717  +hl: O.OMap<K, V>, +hh: O.OMap<K, V>, +khk: {cmp(k, hk) == LT{} : Cmp},
718  +h_l: {Laws.bounded(~K, ~V, ~cmp, hl, Some{k}, Some{hk}) == True{} : Bool}
719) -> {g(~K, ~V, ~cmp, O.OMap.rot_lo.pick(K, V, single, k, v, lo, hk, hv, hl, hh), x)
720      == g(~K, ~V, ~cmp, O.OBin{0, k, v, lo, O.OBin{0, hk, hv, hl, hh}}, x) : Maybe<&2, V>}:
721  match single:
722    case True{}:
723      rot_lo.single.get(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans, x, k, v, lo, hk, hv,
724        hl, hh, khk)
725    case False{}:
726      rot_lo.double.get(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans, hl, x, k, v, lo, hk, hv,
727        hh, khk, h_l)
728
729def rot_lo.get(
730  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~refl: Refl(~K, ~cmp), ~eq: Eq(~K, ~cmp),
731  ~flip: Flip(~K, ~cmp), ~trans: Trans(~K, ~cmp),
732  hi: O.OMap<K, V>, +ub: Maybe<&2, K>, +x: K, +k: K, +v: V, +lo: O.OMap<K, V>,
733  +eh: {Laws.bounded(~K, ~V, ~cmp, hi, Some{k}, ub) == True{} : Bool}
734) -> {g(~K, ~V, ~cmp, O.OMap.rot_lo(K, V, k, v, lo, hi), x)
735      == g(~K, ~V, ~cmp, O.OBin{0, k, v, lo, hi}, x) : Maybe<&2, V>}:
736  match hi:
737    case O.OTip{}:
738      {==}
739    case O.OBin{s, +hk, +hv, +hl, +hh}:
740      rot_lo.pick.get(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans,
741        U32.is_lt((O.OMap.size(K, V, hl) + 1 : U32),
742          (2 * (O.OMap.size(K, V, hh) + 1) : U32)),
743        x, k, v, lo, hk, hv, hl, hh,
744        lt_of(cmp(k, hk), bn.a(~K, ~V, ~cmp, Some{k}, ub, hk, hv, hl, hh, eh)),
745        bn.l(~K, ~V, ~cmp, Some{k}, ub, hk, hv, hl, hh, eh))
746
747def rot_hi.single.get(
748  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~refl: Refl(~K, ~cmp), ~eq: Eq(~K, ~cmp),
749  ~flip: Flip(~K, ~cmp), ~trans: Trans(~K, ~cmp),
750  +x: K, +k: K, +v: V, +lk: K, +lv: V, +ll: O.OMap<K, V>, +lh: O.OMap<K, V>,
751  +hi: O.OMap<K, V>, +lkk: {cmp(lk, k) == LT{} : Cmp}
752) -> {g(~K, ~V, ~cmp, O.OMap.bin(K, V, lk, lv, ll, O.OMap.bin(K, V, k, v, lh, hi)), x)
753      == g(~K, ~V, ~cmp, O.OBin{0, k, v, O.OBin{0, lk, lv, ll, lh}, hi}, x) : Maybe<&2, V>}:
754  +b = {O.OBin{0, k, v, lh, hi} : O.OMap<K, V>}
755  +l = {O.OBin{0, lk, lv, ll, b} : O.OMap<K, V>}
756  +ln = {O.OBin{0, lk, lv, ll, lh} : O.OMap<K, V>}
757  split(c => {g(~K, ~V, ~cmp, l, x) == getc(~K, ~V, ~cmp, c, x, v, ln, hi) : Maybe<&2, V>},
758    cmp(x, k),
759    e => split(c => {getc(~K, ~V, ~cmp, c, x, lv, ll, b)
760        == getc(~K, ~V, ~cmp, c, x, lv, ll, lh) : Maybe<&2, V>},
761      cmp(x, lk),
762      e2 => {==},
763      e2 => {==},
764      e2 => get.lt(~K, ~V, ~cmp, x, k, v, lh, hi, e)),
765    e => rw(K, y => {g(~K, ~V, ~cmp, l, y) == Some{v} : Maybe<&2, V>}, x, k, eq(x, k, e),
766      mtr(V, g(~K, ~V, ~cmp, l, k), g(~K, ~V, ~cmp, b, k), Some{v},
767        get.gt(~K, ~V, ~cmp, k, lk, lv, ll, b, gt_of_lt(~K, ~cmp, ~flip, lk, k, lkk)),
768        get.here(~K, ~V, ~cmp, ~refl, k, v, lh, hi))),
769    +e => mtr(V, g(~K, ~V, ~cmp, l, x), g(~K, ~V, ~cmp, b, x), g(~K, ~V, ~cmp, hi, x),
770      get.gt(~K, ~V, ~cmp, x, lk, lv, ll, b,
771        gt_of_lt(~K, ~cmp, ~flip, lk, x,
772          trans(lk, k, x, lkk, gt_flip(~K, ~cmp, ~flip, x, k, e)))),
773      get.gt(~K, ~V, ~cmp, x, k, v, lh, hi, e)))
774
775def rot_hi.double.get2(
776  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~refl: Refl(~K, ~cmp), ~eq: Eq(~K, ~cmp),
777  ~flip: Flip(~K, ~cmp), ~trans: Trans(~K, ~cmp),
778  +x: K, +k: K, +v: V, +lk: K, +lv: V, +ll: O.OMap<K, V>, +mk: K, +mv: V,
779  +ml: O.OMap<K, V>, +mh: O.OMap<K, V>, +hi: O.OMap<K, V>,
780  +lkm: {cmp(lk, mk) == LT{} : Cmp}, +mkk: {cmp(mk, k) == LT{} : Cmp}
781) -> {g(~K, ~V, ~cmp, O.OMap.bin(K, V, mk, mv, O.OMap.bin(K, V, lk, lv, ll, ml),
782        O.OMap.bin(K, V, k, v, mh, hi)), x)
783      == g(~K, ~V, ~cmp, O.OBin{0, k, v, O.OBin{0, lk, lv, ll, O.OBin{0, mk, mv, ml, mh}}, hi}, x)
784      : Maybe<&2, V>}:
785  +a = {O.OBin{0, lk, lv, ll, ml} : O.OMap<K, V>}
786  +b = {O.OBin{0, k, v, mh, hi} : O.OMap<K, V>}
787  +l = {O.OBin{0, mk, mv, a, b} : O.OMap<K, V>}
788  +m = {O.OBin{0, mk, mv, ml, mh} : O.OMap<K, V>}
789  +ln = {O.OBin{0, lk, lv, ll, m} : O.OMap<K, V>}
790  split(c => {g(~K, ~V, ~cmp, l, x) == getc(~K, ~V, ~cmp, c, x, v, ln, hi) : Maybe<&2, V>},
791    cmp(x, k),
792    +e => split(c => {g(~K, ~V, ~cmp, l, x) == getc(~K, ~V, ~cmp, c, x, lv, ll, m) : Maybe<&2, V>},
793      cmp(x, lk),
794      +e2 => mtr(V, g(~K, ~V, ~cmp, l, x), g(~K, ~V, ~cmp, a, x), g(~K, ~V, ~cmp, ll, x),
795        get.lt(~K, ~V, ~cmp, x, mk, mv, a, b, trans(x, lk, mk, e2, lkm)),
796        get.lt(~K, ~V, ~cmp, x, lk, lv, ll, ml, e2)),
797      e2 => rw(K, y => {g(~K, ~V, ~cmp, l, y) == Some{lv} : Maybe<&2, V>}, x, lk, eq(x, lk, e2),
798        mtr(V, g(~K, ~V, ~cmp, l, lk), g(~K, ~V, ~cmp, a, lk), Some{lv},
799          get.lt(~K, ~V, ~cmp, lk, mk, mv, a, b, lkm),
800          get.here(~K, ~V, ~cmp, ~refl, lk, lv, ll, ml))),
801      +e2 => split(c => {getc(~K, ~V, ~cmp, c, x, mv, a, b)
802          == getc(~K, ~V, ~cmp, c, x, mv, ml, mh) : Maybe<&2, V>},
803        cmp(x, mk),
804        e3 => get.gt(~K, ~V, ~cmp, x, lk, lv, ll, ml, e2),
805        e3 => {==},
806        e3 => get.lt(~K, ~V, ~cmp, x, k, v, mh, hi, e))),
807    e => rw(K, y => {g(~K, ~V, ~cmp, l, y) == Some{v} : Maybe<&2, V>}, x, k, eq(x, k, e),
808      mtr(V, g(~K, ~V, ~cmp, l, k), g(~K, ~V, ~cmp, b, k), Some{v},
809        get.gt(~K, ~V, ~cmp, k, mk, mv, a, b, gt_of_lt(~K, ~cmp, ~flip, mk, k, mkk)),
810        get.here(~K, ~V, ~cmp, ~refl, k, v, mh, hi))),
811    +e => mtr(V, g(~K, ~V, ~cmp, l, x), g(~K, ~V, ~cmp, b, x), g(~K, ~V, ~cmp, hi, x),
812      get.gt(~K, ~V, ~cmp, x, mk, mv, a, b,
813        gt_of_lt(~K, ~cmp, ~flip, mk, x,
814          trans(mk, k, x, mkk, gt_flip(~K, ~cmp, ~flip, x, k, e)))),
815      get.gt(~K, ~V, ~cmp, x, k, v, mh, hi, e)))
816
817def rot_hi.double.get(
818  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~refl: Refl(~K, ~cmp), ~eq: Eq(~K, ~cmp),
819  ~flip: Flip(~K, ~cmp), ~trans: Trans(~K, ~cmp),
820  lh: O.OMap<K, V>, +x: K, +k: K, +v: V, +lk: K, +lv: V, +ll: O.OMap<K, V>,
821  +hi: O.OMap<K, V>, +lkk: {cmp(lk, k) == LT{} : Cmp},
822  +l_h: {Laws.bounded(~K, ~V, ~cmp, lh, Some{lk}, Some{k}) == True{} : Bool}
823) -> {g(~K, ~V, ~cmp, O.OMap.rot_hi.double(K, V, k, v, lk, lv, ll, lh, hi), x)
824      == g(~K, ~V, ~cmp, O.OBin{0, k, v, O.OBin{0, lk, lv, ll, lh}, hi}, x) : Maybe<&2, V>}:
825  match lh:
826    case O.OTip{}:
827      rot_hi.single.get(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans, x, k, v, lk, lv, ll,
828        O.OTip{}, hi, lkk)
829    case O.OBin{s, +mk, +mv, +ml, +mh}:
830      rot_hi.double.get2(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans, x, k, v, lk, lv, ll,
831        mk, mv, ml, mh, hi,
832        lt_of(cmp(lk, mk), bn.a(~K, ~V, ~cmp, Some{lk}, Some{k}, mk, mv, ml, mh, l_h)),
833        lt_of(cmp(mk, k), bn.b(~K, ~V, ~cmp, Some{lk}, Some{k}, mk, mv, ml, mh, l_h)))
834
835def rot_hi.pick.get(
836  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~refl: Refl(~K, ~cmp), ~eq: Eq(~K, ~cmp),
837  ~flip: Flip(~K, ~cmp), ~trans: Trans(~K, ~cmp),
838  single: Bool, +x: K, +k: K, +v: V, +lk: K, +lv: V, +ll: O.OMap<K, V>,
839  +lh: O.OMap<K, V>, +hi: O.OMap<K, V>, +lkk: {cmp(lk, k) == LT{} : Cmp},
840  +l_h: {Laws.bounded(~K, ~V, ~cmp, lh, Some{lk}, Some{k}) == True{} : Bool}
841) -> {g(~K, ~V, ~cmp, O.OMap.rot_hi.pick(K, V, single, k, v, lk, lv, ll, lh, hi), x)
842      == g(~K, ~V, ~cmp, O.OBin{0, k, v, O.OBin{0, lk, lv, ll, lh}, hi}, x) : Maybe<&2, V>}:
843  match single:
844    case True{}:
845      rot_hi.single.get(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans, x, k, v, lk, lv, ll,
846        lh, hi, lkk)
847    case False{}:
848      rot_hi.double.get(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans, lh, x, k, v, lk, lv,
849        ll, hi, lkk, l_h)
850
851def rot_hi.get(
852  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~refl: Refl(~K, ~cmp), ~eq: Eq(~K, ~cmp),
853  ~flip: Flip(~K, ~cmp), ~trans: Trans(~K, ~cmp),
854  lo: O.OMap<K, V>, +lb: Maybe<&2, K>, +x: K, +k: K, +v: V, +hi: O.OMap<K, V>,
855  +el: {Laws.bounded(~K, ~V, ~cmp, lo, lb, Some{k}) == True{} : Bool}
856) -> {g(~K, ~V, ~cmp, O.OMap.rot_hi(K, V, k, v, lo, hi), x)
857      == g(~K, ~V, ~cmp, O.OBin{0, k, v, lo, hi}, x) : Maybe<&2, V>}:
858  match lo:
859    case O.OTip{}:
860      {==}
861    case O.OBin{s, +lk, +lv, +ll, +lh}:
862      rot_hi.pick.get(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans,
863        U32.is_lt((O.OMap.size(K, V, lh) + 1 : U32),
864          (2 * (O.OMap.size(K, V, ll) + 1) : U32)),
865        x, k, v, lk, lv, ll, lh, hi,
866        lt_of(cmp(lk, k), bn.b(~K, ~V, ~cmp, lb, Some{k}, lk, lv, ll, lh, el)),
867        bn.h(~K, ~V, ~cmp, lb, Some{k}, lk, lv, ll, lh, el))
868
869def balance.if.get(
870  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~refl: Refl(~K, ~cmp), ~eq: Eq(~K, ~cmp),
871  ~flip: Flip(~K, ~cmp), ~trans: Trans(~K, ~cmp),
872  heavy_hi: Bool, heavy_lo: Bool, +lb: Maybe<&2, K>, +ub: Maybe<&2, K>, +x: K,
873  +k: K, +v: V, +lo: O.OMap<K, V>, +hi: O.OMap<K, V>,
874  el: {Laws.bounded(~K, ~V, ~cmp, lo, lb, Some{k}) == True{} : Bool},
875  eh: {Laws.bounded(~K, ~V, ~cmp, hi, Some{k}, ub) == True{} : Bool}
876) -> {g(~K, ~V, ~cmp, O.OMap.balance.if(K, V, heavy_hi, heavy_lo, k, v, lo, hi), x)
877      == g(~K, ~V, ~cmp, O.OBin{0, k, v, lo, hi}, x) : Maybe<&2, V>}:
878  match heavy_hi heavy_lo:
879    case True{} _:
880      rot_lo.get(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans, hi, ub, x, k, v, lo, eh)
881    case False{} True{}:
882      rot_hi.get(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans, lo, lb, x, k, v, hi, el)
883    case False{} False{}:
884      {==}
885
886def balance.get(
887  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~refl: Refl(~K, ~cmp), ~eq: Eq(~K, ~cmp),
888  ~flip: Flip(~K, ~cmp), ~trans: Trans(~K, ~cmp),
889  +lb: Maybe<&2, K>, +ub: Maybe<&2, K>, +x: K, +k: K, +v: V, +lo: O.OMap<K, V>,
890  +hi: O.OMap<K, V>,
891  el: {Laws.bounded(~K, ~V, ~cmp, lo, lb, Some{k}) == True{} : Bool},
892  eh: {Laws.bounded(~K, ~V, ~cmp, hi, Some{k}, ub) == True{} : Bool}
893) -> {g(~K, ~V, ~cmp, O.OMap.balance(K, V, k, v, lo, hi), x)
894      == g(~K, ~V, ~cmp, O.OBin{0, k, v, lo, hi}, x) : Maybe<&2, V>}:
895  +wl = (O.OMap.size(K, V, lo) + 1 : U32)
896  +wh = (O.OMap.size(K, V, hi) + 1 : U32)
897  balance.if.get(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans, U32.is_gt(wh, (3 * wl : U32)),
898    U32.is_gt(wl, (3 * wh : U32)), lb, ub, x, k, v, lo, hi, el, eh)
899
900def get_put_same(
901  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~refl: Refl(~K, ~cmp), ~eq: Eq(~K, ~cmp),
902  ~flip: Flip(~K, ~cmp), ~trans: Trans(~K, ~cmp),
903  t: O.OMap<K, V>, +lb: Maybe<&2, K>, +ub: Maybe<&2, K>, +k: K, +v: V,
904  +bt: {Laws.bounded(~K, ~V, ~cmp, t, lb, ub) == True{} : Bool},
905  +ea: {Laws.above(~K, ~cmp, lb, k) == True{} : Bool},
906  +eb: {Laws.below(~K, ~cmp, ub, k) == True{} : Bool}
907) -> {g(~K, ~V, ~cmp, O.OMap.put(~K, ~V, ~cmp, t, k, v), k) == Some{v} : Maybe<&2, V>}:
908  match t:
909    case O.OTip{}:
910      get.here(~K, ~V, ~cmp, ~refl, k, v, O.OTip{}, O.OTip{})
911    case O.OBin{+s, +key, +val, +lo, +hi}:
912      +b_l = bn.l(~K, ~V, ~cmp, lb, ub, key, val, lo, hi, bt)
913      +b_h = bn.h(~K, ~V, ~cmp, lb, ub, key, val, lo, hi, bt)
914      +plo = O.OMap.put(~K, ~V, ~cmp, lo, k, v)
915      +phi = O.OMap.put(~K, ~V, ~cmp, hi, k, v)
916      cmp.split(O.OMap<K, V>, Maybe<&2, V>, y => g(~K, ~V, ~cmp, y, k), Some{v},
917        cmp(k, key),
918        u => O.OMap.balance(K, V, key, val, O.OMap.put(~K, ~V, ~cmp, lo, k, v), hi),
919        u => O.OBin{s, key, v, lo, hi},
920        u => O.OMap.balance(K, V, key, val, lo, O.OMap.put(~K, ~V, ~cmp, hi, k, v)),
921        +e => mtr(V, g(~K, ~V, ~cmp, O.OMap.balance(K, V, key, val, plo, hi), k),
922          g(~K, ~V, ~cmp, O.OBin{0, key, val, plo, hi}, k), Some{v},
923          balance.get(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans, lb, ub, k, key, val, plo, hi,
924            put.bnd(~K, ~V, ~cmp, ~flip, ~trans, lo, lb, Some{key}, k, v, b_l, ea,
925              lt_true(cmp(k, key), e)),
926            b_h),
927          mtr(V, g(~K, ~V, ~cmp, O.OBin{0, key, val, plo, hi}, k), g(~K, ~V, ~cmp, plo, k),
928            Some{v},
929            get.lt(~K, ~V, ~cmp, k, key, val, plo, hi, e),
930            get_put_same(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans, lo, lb, Some{key}, k, v,
931              b_l, ea, lt_true(cmp(k, key), e)))),
932        e => rw(Cmp, c => {getc(~K, ~V, ~cmp, c, k, v, lo, hi) == Some{v} : Maybe<&2, V>},
933          cmp(k, key), EQ{}, e, {==}),
934        +e => mtr(V, g(~K, ~V, ~cmp, O.OMap.balance(K, V, key, val, lo, phi), k),
935          g(~K, ~V, ~cmp, O.OBin{0, key, val, lo, phi}, k), Some{v},
936          balance.get(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans, lb, ub, k, key, val, lo, phi,
937            b_l,
938            put.bnd(~K, ~V, ~cmp, ~flip, ~trans, hi, Some{key}, ub, k, v, b_h,
939              lt_true(cmp(key, k), gt_flip(~K, ~cmp, ~flip, k, key, e)), eb)),
940          mtr(V, g(~K, ~V, ~cmp, O.OBin{0, key, val, lo, phi}, k), g(~K, ~V, ~cmp, phi, k),
941            Some{v},
942            get.gt(~K, ~V, ~cmp, k, key, val, lo, phi, e),
943            get_put_same(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans, hi, Some{key}, ub, k, v,
944              b_h, lt_true(cmp(key, k), gt_flip(~K, ~cmp, ~flip, k, key, e)), eb))))
945
946def Laws.omap_get_put_same(K, V, cmp, refl, eq, flip, trans, m, tree, k, v):
947  get_put_same(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans, m, None{}, None{}, k, v, tree,
948    {==}, {==})
949
950def neq_false(c: Cmp, ne: {c != EQ{} : Cmp}) -> {Cmp.is_eq(c) == False{} : Bool}:
951  match c:
952    case LT{}:
953      {==}
954    case EQ{}:
955      Empty.absurd({Cmp.is_eq(EQ{}) == False{} : Bool}, ne({==}))
956    case GT{}:
957      {==}
958
959def ne_absurd(
960  -A: Type, -c: Cmp, nef: {Cmp.is_eq(c) == False{} : Bool}, e: {c == EQ{} : Cmp}
961) -> A:
962  +tf = Equal.trans(Bool, True{}, Cmp.is_eq(c), False{},
963    Equal.sym(Bool, Cmp.is_eq(c), True{}, Equal.cong(Cmp, Bool, x => Cmp.is_eq(x), c, EQ{}, e)),
964    nef)
965  Empty.absurd(A, MBool.false_ne_true()(Equal.sym(Bool, True{}, False{}, tf)))
966
967def eq_flip(
968  ~K: Data, ~cmp: K -> K -> Cmp, ~flip: Flip(~K, ~cmp), +x: K, +y: K,
969  e: {cmp(x, y) == EQ{} : Cmp}
970) -> {cmp(y, x) == EQ{} : Cmp}:
971  Equal.trans(Cmp, cmp(y, x), Laws.flip(cmp(x, y)), EQ{}, flip(x, y),
972    Equal.cong(Cmp, Cmp, c => Laws.flip(c), cmp(x, y), EQ{}, e))
973
974def get_put_other(
975  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~refl: Refl(~K, ~cmp), ~eq: Eq(~K, ~cmp),
976  ~flip: Flip(~K, ~cmp), ~trans: Trans(~K, ~cmp),
977  t: O.OMap<K, V>, +lb: Maybe<&2, K>, +ub: Maybe<&2, K>, +k2: K, +k: K, +v: V,
978  +bt: {Laws.bounded(~K, ~V, ~cmp, t, lb, ub) == True{} : Bool},
979  +ea: {Laws.above(~K, ~cmp, lb, k2) == True{} : Bool},
980  +eb: {Laws.below(~K, ~cmp, ub, k2) == True{} : Bool},
981  +nef: {Cmp.is_eq(cmp(k2, k)) == False{} : Bool}
982) -> {g(~K, ~V, ~cmp, O.OMap.put(~K, ~V, ~cmp, t, k2, v), k)
983      == g(~K, ~V, ~cmp, t, k) : Maybe<&2, V>}:
984  match t:
985    case O.OTip{}:
986      split(c => {getc(~K, ~V, ~cmp, c, k, v, O.OTip{}, O.OTip{}) == None{} : Maybe<&2, V>},
987        cmp(k, k2),
988        e => {==},
989        e => ne_absurd({Some{v} == None{} : Maybe<&2, V>}, cmp(k2, k), nef,
990          eq_flip(~K, ~cmp, ~flip, k, k2, e)),
991        e => {==})
992    case O.OBin{+s, +key, +val, +lo, +hi}:
993      +b_l = bn.l(~K, ~V, ~cmp, lb, ub, key, val, lo, hi, bt)
994      +b_h = bn.h(~K, ~V, ~cmp, lb, ub, key, val, lo, hi, bt)
995      +plo = O.OMap.put(~K, ~V, ~cmp, lo, k2, v)
996      +phi = O.OMap.put(~K, ~V, ~cmp, hi, k2, v)
997      +old = {O.OBin{s, key, val, lo, hi} : O.OMap<K, V>}
998      cmp.split(O.OMap<K, V>, Maybe<&2, V>, y => g(~K, ~V, ~cmp, y, k),
999        g(~K, ~V, ~cmp, old, k), cmp(k2, key),
1000        u => O.OMap.balance(K, V, key, val, O.OMap.put(~K, ~V, ~cmp, lo, k2, v), hi),
1001        u => O.OBin{s, key, v, lo, hi},
1002        u => O.OMap.balance(K, V, key, val, lo, O.OMap.put(~K, ~V, ~cmp, hi, k2, v)),
1003        +e => mtr(V, g(~K, ~V, ~cmp, O.OMap.balance(K, V, key, val, plo, hi), k),
1004          g(~K, ~V, ~cmp, O.OBin{0, key, val, plo, hi}, k), g(~K, ~V, ~cmp, old, k),
1005          balance.get(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans, lb, ub, k, key, val, plo, hi,
1006            put.bnd(~K, ~V, ~cmp, ~flip, ~trans, lo, lb, Some{key}, k2, v, b_l, ea,
1007              lt_true(cmp(k2, key), e)),
1008            b_h),
1009          split(c => {getc(~K, ~V, ~cmp, c, k, val, plo, hi)
1010              == getc(~K, ~V, ~cmp, c, k, val, lo, hi) : Maybe<&2, V>},
1011            cmp(k, key),
1012            e2 => get_put_other(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans, lo, lb, Some{key},
1013              k2, k, v, b_l, ea, lt_true(cmp(k2, key), e), nef),
1014            e2 => {==},
1015            e2 => {==})),
1016        +e => split(c => {getc(~K, ~V, ~cmp, c, k, v, lo, hi)
1017            == getc(~K, ~V, ~cmp, c, k, val, lo, hi) : Maybe<&2, V>},
1018          cmp(k, key),
1019          e2 => {==},
1020          e2 => ne_absurd({Some{v} == Some{val} : Maybe<&2, V>}, cmp(k2, k), nef,
1021            rw(K, y => {cmp(y, k) == EQ{} : Cmp}, k2, key, eq(k2, key, e),
1022              eq_flip(~K, ~cmp, ~flip, k, key, e2))),
1023          e2 => {==}),
1024        +e => mtr(V, g(~K, ~V, ~cmp, O.OMap.balance(K, V, key, val, lo, phi), k),
1025          g(~K, ~V, ~cmp, O.OBin{0, key, val, lo, phi}, k), g(~K, ~V, ~cmp, old, k),
1026          balance.get(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans, lb, ub, k, key, val, lo, phi,
1027            b_l,
1028            put.bnd(~K, ~V, ~cmp, ~flip, ~trans, hi, Some{key}, ub, k2, v, b_h,
1029              lt_true(cmp(key, k2), gt_flip(~K, ~cmp, ~flip, k2, key, e)), eb)),
1030          split(c => {getc(~K, ~V, ~cmp, c, k, val, lo, phi)
1031              == getc(~K, ~V, ~cmp, c, k, val, lo, hi) : Maybe<&2, V>},
1032            cmp(k, key),
1033            e2 => {==},
1034            e2 => {==},
1035            e2 => get_put_other(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans, hi, Some{key}, ub,
1036              k2, k, v, b_h, lt_true(cmp(key, k2), gt_flip(~K, ~cmp, ~flip, k2, key, e)),
1037              eb, nef))))
1038
1039def Laws.omap_get_put_other_key(K, V, cmp, refl, eq, flip, trans, m, tree, k2, k, ne, v):
1040  get_put_other(~K, ~V, ~cmp, ~refl, ~eq, ~flip, ~trans, m, None{}, None{}, k2, k, v, tree,
1041    {==}, {==}, neq_false(cmp(k2, k), ne))
1042
1043# A tree bounded above by a is bounded above by anything above a.
1044def weaken_hi(
1045  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~trans: Trans(~K, ~cmp),
1046  t: O.OMap<K, V>, +lb: Maybe<&2, K>, +a: K, +ub: Maybe<&2, K>,
1047  +e: {Laws.bounded(~K, ~V, ~cmp, t, lb, Some{a}) == True{} : Bool},
1048  +eab: {Laws.below(~K, ~cmp, ub, a) == True{} : Bool}
1049) -> {Laws.bounded(~K, ~V, ~cmp, t, lb, ub) == True{} : Bool}:
1050  match t:
1051    case O.OTip{}:
1052      {==}
1053    case O.OBin{s, +k, +v, +lo, +hi}:
1054      bn.i(~K, ~V, ~cmp, lb, ub, k, v, lo, hi,
1055        bn.a(~K, ~V, ~cmp, lb, Some{a}, k, v, lo, hi, e),
1056        below_trans(~K, ~cmp, ~trans, ub, k, a,
1057          bn.b(~K, ~V, ~cmp, lb, Some{a}, k, v, lo, hi, e), eab),
1058        bn.l(~K, ~V, ~cmp, lb, Some{a}, k, v, lo, hi, e),
1059        weaken_hi(~K, ~V, ~cmp, ~trans, hi, Some{k}, a, ub,
1060          bn.h(~K, ~V, ~cmp, lb, Some{a}, k, v, lo, hi, e), eab))
1061
1062# What pop_min answers: its key lies between the bounds, and the rest lies above it.
1063def PM(
1064  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, +lb: Maybe<&2, K>, +ub: Maybe<&2, K>,
1065  r: K & V & O.OMap<K, V>
1066) -> Bool:
1067  (+mk, mv, t) = r
1068  Bool.and(Bool.and(Laws.above(~K, ~cmp, lb, mk), Laws.below(~K, ~cmp, ub, mk)),
1069    Laws.bounded(~K, ~V, ~cmp, t, Some{mk}, ub))
1070
1071def pm.fin.bnd.go(
1072  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~trans: Trans(~K, ~cmp),
1073  +mk: K, +mv: V, +t: O.OMap<K, V>, +lb: Maybe<&2, K>, +ub: Maybe<&2, K>, +k: K,
1074  +v: V, +hi: O.OMap<K, V>,
1075  +ih: {PM(~K, ~V, ~cmp, lb, Some{k}, {(mk, mv, t) : K & V & O.OMap<K, V>}) == True{} : Bool},
1076  +eb: {Laws.below(~K, ~cmp, ub, k) == True{} : Bool},
1077  eh: {Laws.bounded(~K, ~V, ~cmp, hi, Some{k}, ub) == True{} : Bool}
1078) -> {PM(~K, ~V, ~cmp, lb, ub,
1079       O.OMap.pop_min.fin(K, V, k, v, hi, {(mk, mv, t) : K & V & O.OMap<K, V>})) == True{} : Bool}:
1080  +ab = Bool.and(Laws.above(~K, ~cmp, lb, mk), Laws.below(~K, ~cmp, Some{k}, mk))
1081  +c = Laws.bounded(~K, ~V, ~cmp, t, Some{mk}, Some{k})
1082  +eab = MBool.eq_true_of_and_left(ab, c, ih)
1083  +mkk = MBool.eq_true_of_and_right(Laws.above(~K, ~cmp, lb, mk), Laws.below(~K, ~cmp, Some{k}, mk), eab)
1084  MBool.and_eq_true(Bool.and(Laws.above(~K, ~cmp, lb, mk), Laws.below(~K, ~cmp, ub, mk)), Laws.bounded(~K, ~V, ~cmp, O.OMap.balance(K, V, k, v, t, hi), Some{mk}, ub), MBool.and_eq_true(Laws.above(~K, ~cmp, lb, mk), Laws.below(~K, ~cmp, ub, mk), MBool.eq_true_of_and_left(Laws.above(~K, ~cmp, lb, mk), Laws.below(~K, ~cmp, Some{k}, mk), eab), below_trans(~K, ~cmp, ~trans, ub, mk, k, mkk, eb)), balance.bnd(~K, ~V, ~cmp, ~trans, Some{mk}, ub, k, v, t, hi, mkk, eb,
1085      MBool.eq_true_of_and_right(ab, c, ih), eh))
1086
1087# Workaround for https://github.com/bendlang/bend/issues/1077: bind the tuple without +.
1088def pm.fin.bnd(
1089  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~trans: Trans(~K, ~cmp),
1090  r: K & V & O.OMap<K, V>, +lb: Maybe<&2, K>, +ub: Maybe<&2, K>, +k: K, +v: V,
1091  +hi: O.OMap<K, V>,
1092  ih: {PM(~K, ~V, ~cmp, lb, Some{k}, r) == True{} : Bool},
1093  eb: {Laws.below(~K, ~cmp, ub, k) == True{} : Bool},
1094  eh: {Laws.bounded(~K, ~V, ~cmp, hi, Some{k}, ub) == True{} : Bool}
1095) -> {PM(~K, ~V, ~cmp, lb, ub, O.OMap.pop_min.fin(K, V, k, v, hi, r)) == True{} : Bool}:
1096  (mk, rest) = r
1097  (mv, t) = rest
1098  pm.fin.bnd.go(~K, ~V, ~cmp, ~trans, mk, mv, t, lb, ub, k, v, hi, ih, eb, eh)
1099
1100def pm.bnd(
1101  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~trans: Trans(~K, ~cmp),
1102  lo: O.OMap<K, V>, +lb: Maybe<&2, K>, +ub: Maybe<&2, K>, +k: K, +v: V,
1103  +hi: O.OMap<K, V>,
1104  +e: {Laws.bounded(~K, ~V, ~cmp, O.OBin{0, k, v, lo, hi}, lb, ub) == True{} : Bool}
1105) -> {PM(~K, ~V, ~cmp, lb, ub, O.OMap.pop_min(K, V, lo, k, v, hi)) == True{} : Bool}:
1106  match lo:
1107    case O.OTip{}:
1108      MBool.and_eq_true(Bool.and(Laws.above(~K, ~cmp, lb, k), Laws.below(~K, ~cmp, ub, k)), Laws.bounded(~K, ~V, ~cmp, hi, Some{k}, ub), MBool.and_eq_true(Laws.above(~K, ~cmp, lb, k), Laws.below(~K, ~cmp, ub, k), bn.a(~K, ~V, ~cmp, lb, ub, k, v, O.OTip{}, hi, e), bn.b(~K, ~V, ~cmp, lb, ub, k, v, O.OTip{}, hi, e)), bn.h(~K, ~V, ~cmp, lb, ub, k, v, O.OTip{}, hi, e))
1109    case O.OBin{s, +lk, +lv, +ll, +lh}:
1110      +lo = {O.OBin{0, lk, lv, ll, lh} : O.OMap<K, V>}
1111      pm.fin.bnd(~K, ~V, ~cmp, ~trans, O.OMap.pop_min(K, V, ll, lk, lv, lh), lb, ub, k, v, hi,
1112        pm.bnd(~K, ~V, ~cmp, ~trans, ll, lb, Some{k}, lk, lv, lh,
1113          bn.l(~K, ~V, ~cmp, lb, ub, k, v, lo, hi, e)),
1114        bn.b(~K, ~V, ~cmp, lb, ub, k, v, lo, hi, e),
1115        bn.h(~K, ~V, ~cmp, lb, ub, k, v, lo, hi, e))
1116
1117def glue.fin.bnd.go(
1118  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~trans: Trans(~K, ~cmp),
1119  +mk: K, +mv: V, +t: O.OMap<K, V>, +lo: O.OMap<K, V>, +lb: Maybe<&2, K>,
1120  +ub: Maybe<&2, K>, +key: K,
1121  eka: {Laws.above(~K, ~cmp, lb, key) == True{} : Bool},
1122  el: {Laws.bounded(~K, ~V, ~cmp, lo, lb, Some{key}) == True{} : Bool},
1123  +pmr: {PM(~K, ~V, ~cmp, Some{key}, ub, {(mk, mv, t) : K & V & O.OMap<K, V>}) == True{} : Bool}
1124) -> {Laws.bounded(~K, ~V, ~cmp,
1125       O.OMap.glue.fin(K, V, lo, {(mk, mv, t) : K & V & O.OMap<K, V>}), lb, ub) == True{} : Bool}:
1126  +ab = Bool.and(Laws.above(~K, ~cmp, Some{key}, mk), Laws.below(~K, ~cmp, ub, mk))
1127  +c = Laws.bounded(~K, ~V, ~cmp, t, Some{mk}, ub)
1128  +eab = MBool.eq_true_of_and_left(ab, c, pmr)
1129  +km = MBool.eq_true_of_and_left(Laws.above(~K, ~cmp, Some{key}, mk), Laws.below(~K, ~cmp, ub, mk), eab)
1130  balance.bnd(~K, ~V, ~cmp, ~trans, lb, ub, mk, mv, lo, t,
1131    above_trans(~K, ~cmp, ~trans, lb, key, mk, eka, km),
1132    MBool.eq_true_of_and_right(Laws.above(~K, ~cmp, Some{key}, mk), Laws.below(~K, ~cmp, ub, mk), eab),
1133    weaken_hi(~K, ~V, ~cmp, ~trans, lo, lb, key, Some{mk}, el, km),
1134    MBool.eq_true_of_and_right(ab, c, pmr))
1135
1136# Workaround for https://github.com/bendlang/bend/issues/1077: bind the tuple without +.
1137def glue.fin.bnd(
1138  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~trans: Trans(~K, ~cmp),
1139  r: K & V & O.OMap<K, V>, +lo: O.OMap<K, V>, +lb: Maybe<&2, K>,
1140  +ub: Maybe<&2, K>, +key: K,
1141  eka: {Laws.above(~K, ~cmp, lb, key) == True{} : Bool},
1142  el: {Laws.bounded(~K, ~V, ~cmp, lo, lb, Some{key}) == True{} : Bool},
1143  pmr: {PM(~K, ~V, ~cmp, Some{key}, ub, r) == True{} : Bool}
1144) -> {Laws.bounded(~K, ~V, ~cmp, O.OMap.glue.fin(K, V, lo, r), lb, ub) == True{} : Bool}:
1145  (mk, rest) = r
1146  (mv, t) = rest
1147  glue.fin.bnd.go(~K, ~V, ~cmp, ~trans, mk, mv, t, lo, lb, ub, key, eka, el, pmr)
1148
1149def glue.bnd(
1150  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~trans: Trans(~K, ~cmp),
1151  hi: O.OMap<K, V>, +lo: O.OMap<K, V>, +lb: Maybe<&2, K>, +ub: Maybe<&2, K>,
1152  +key: K,
1153  eka: {Laws.above(~K, ~cmp, lb, key) == True{} : Bool},
1154  ekb: {Laws.below(~K, ~cmp, ub, key) == True{} : Bool},
1155  el: {Laws.bounded(~K, ~V, ~cmp, lo, lb, Some{key}) == True{} : Bool},
1156  eh: {Laws.bounded(~K, ~V, ~cmp, hi, Some{key}, ub) == True{} : Bool}
1157) -> {Laws.bounded(~K, ~V, ~cmp, O.OMap.glue(K, V, lo, hi), lb, ub) == True{} : Bool}:
1158  match hi:
1159    case O.OTip{}:
1160      weaken_hi(~K, ~V, ~cmp, ~trans, lo, lb, key, ub, el, ekb)
1161    case O.OBin{s, +k, +v, +hl, +hh}:
1162      glue.fin.bnd(~K, ~V, ~cmp, ~trans, O.OMap.pop_min(K, V, hl, k, v, hh), lo, lb, ub, key,
1163        eka, el, pm.bnd(~K, ~V, ~cmp, ~trans, hl, Some{key}, ub, k, v, hh, eh))
1164
1165def del.bnd(
1166  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, ~trans: Trans(~K, ~cmp),
1167  t: O.OMap<K, V>, +lb: Maybe<&2, K>, +ub: Maybe<&2, K>, +k: K,
1168  +bt: {Laws.bounded(~K, ~V, ~cmp, t, lb, ub) == True{} : Bool}
1169) -> {Laws.bounded(~K, ~V, ~cmp, O.OMap.del(~K, ~V, ~cmp, t, k), lb, ub) == True{} : Bool}:
1170  match t:
1171    case O.OTip{}:
1172      {==}
1173    case O.OBin{+s, +key, +val, +lo, +hi}:
1174      +b_a = bn.a(~K, ~V, ~cmp, lb, ub, key, val, lo, hi, bt)
1175      +b_b = bn.b(~K, ~V, ~cmp, lb, ub, key, val, lo, hi, bt)
1176      +b_l = bn.l(~K, ~V, ~cmp, lb, ub, key, val, lo, hi, bt)
1177      +b_h = bn.h(~K, ~V, ~cmp, lb, ub, key, val, lo, hi, bt)
1178      cmp.split(O.OMap<K, V>, Bool, y => Laws.bounded(~K, ~V, ~cmp, y, lb, ub), True{},
1179        cmp(k, key),
1180        u => O.OMap.balance(K, V, key, val, O.OMap.del(~K, ~V, ~cmp, lo, k), hi),
1181        u => O.OMap.glue(K, V, lo, hi),
1182        u => O.OMap.balance(K, V, key, val, lo, O.OMap.del(~K, ~V, ~cmp, hi, k)),
1183        e => balance.bnd(~K, ~V, ~cmp, ~trans, lb, ub, key, val,
1184          O.OMap.del(~K, ~V, ~cmp, lo, k), hi, b_a, b_b,
1185          del.bnd(~K, ~V, ~cmp, ~trans, lo, lb, Some{key}, k, b_l), b_h),
1186        e => glue.bnd(~K, ~V, ~cmp, ~trans, hi, lo, lb, ub, key, b_a, b_b, b_l, b_h),
1187        e => balance.bnd(~K, ~V, ~cmp, ~trans, lb, ub, key, val, lo,
1188          O.OMap.del(~K, ~V, ~cmp, hi, k), b_a, b_b, b_l,
1189          del.bnd(~K, ~V, ~cmp, ~trans, hi, Some{key}, ub, k, b_h)))
1190
1191def Laws.omap_del_searchtree(K, V, cmp, refl, eq, flip, trans, m, tree, k):
1192  del.bnd(~K, ~V, ~cmp, ~trans, m, None{}, None{}, k, tree)
1193
1194def Laws.omap_new_weight_balanced(K, V):
1195  {==}
1196
1197# --- weight balance -------------------------------------------------------------
1198
1199def W(-K: Data, -V: Data, t: O.OMap<K, V>) -> Nat:
1200  Laws.omap_weight(K, V, t)
1201
1202def WB(-K: Data, -V: Data, t: O.OMap<K, V>) -> Bool:
1203  Laws.weight_balanced(K, V, t)
1204
1205# t is balanced and its weight is within one of n.
1206def PW(-K: Data, -V: Data, +n: Nat, +t: O.OMap<K, V>) -> Bool:
1207  Bool.and(WB(K, V, t), Ord.near(n, W(K, V, t)))
1208
1209def PMW(-K: Data, -V: Data, +n: Nat, r: K & V & O.OMap<K, V>) -> Bool:
1210  (mk, mv, t) = r
1211  PW(K, V, n, t)
1212
1213def pos_add(a: Nat, +b: Nat, e: Ord.LE(1n, a)) -> Ord.LE(1n, Nat.add(a, b)):
1214  match a:
1215    case 0n:
1216      Empty.absurd(Ord.LE(1n, b), MBool.false_ne_true()(e))
1217    case 1n+p:
1218      MNat.zero_le(Nat.add(p, b))
1219
1220def w_pos(-K: Data, -V: Data, t: O.OMap<K, V>) -> Ord.LE(1n, W(K, V, t)):
1221  match t:
1222    case O.OTip{}:
1223      {==}
1224    case O.OBin{s, k, v, +lo, +hi}:
1225      pos_add(W(K, V, lo), W(K, V, hi), w_pos(K, V, lo))
1226
1227def wb.ok(
1228  -K: Data, -V: Data, -k: K, -v: V, +lo: O.OMap<K, V>, +hi: O.OMap<K, V>,
1229  e: {WB(K, V, O.OBin{0, k, v, lo, hi}) == True{} : Bool}
1230) -> {Laws.weight_ok(W(K, V, lo), W(K, V, hi)) == True{} : Bool}:
1231  c3.a(Laws.weight_ok(W(K, V, lo), W(K, V, hi)), WB(K, V, lo), WB(K, V, hi), e)
1232
1233def wb.l(
1234  -K: Data, -V: Data, -k: K, -v: V, +lo: O.OMap<K, V>, +hi: O.OMap<K, V>,
1235  e: {WB(K, V, O.OBin{0, k, v, lo, hi}) == True{} : Bool}
1236) -> {WB(K, V, lo) == True{} : Bool}:
1237  c3.b(Laws.weight_ok(W(K, V, lo), W(K, V, hi)), WB(K, V, lo), WB(K, V, hi), e)
1238
1239def wb.h(
1240  -K: Data, -V: Data, -k: K, -v: V, +lo: O.OMap<K, V>, +hi: O.OMap<K, V>,
1241  e: {WB(K, V, O.OBin{0, k, v, lo, hi}) == True{} : Bool}
1242) -> {WB(K, V, hi) == True{} : Bool}:
1243  c3.c(Laws.weight_ok(W(K, V, lo), W(K, V, hi)), WB(K, V, lo), WB(K, V, hi), e)
1244
1245def wb.i(
1246  -K: Data, -V: Data, -k: K, -v: V, +lo: O.OMap<K, V>, +hi: O.OMap<K, V>,
1247  eo: {Laws.weight_ok(W(K, V, lo), W(K, V, hi)) == True{} : Bool},
1248  el: {WB(K, V, lo) == True{} : Bool}, eh: {WB(K, V, hi) == True{} : Bool}
1249) -> {WB(K, V, O.OBin{0, k, v, lo, hi}) == True{} : Bool}:
1250  c3.i(Laws.weight_ok(W(K, V, lo), W(K, V, hi)), WB(K, V, lo), WB(K, V, hi), eo, el, eh)
1251
1252# Rotations toward lo, after hi grew or lo shrank by one.
1253def rls.wb(
1254  -K: Data, -V: Data, +k: K, +v: V, +lo: O.OMap<K, V>, +hk: K, +hv: V,
1255  +hl: O.OMap<K, V>, +hh: O.OMap<K, V>,
1256  wbl: {WB(K, V, lo) == True{} : Bool},
1257  +wbh: {WB(K, V, O.OBin{0, hk, hv, hl, hh}) == True{} : Bool},
1258  +heavy: Ord.LE(1n+Nat.mul(3n, W(K, V, lo)), Nat.add(W(K, V, hl), W(K, V, hh))),
1259  +alm: Ord.LE(Nat.add(W(K, V, hl), W(K, V, hh)), Nat.add(3n, Nat.mul(3n, W(K, V, lo)))),
1260  +hs: Ord.LE(1n+W(K, V, hl), Nat.mul(2n, W(K, V, hh)))
1261) -> {WB(K, V, O.OMap.bin(K, V, hk, hv, O.OMap.bin(K, V, k, v, lo, hl), hh)) == True{} : Bool}:
1262  +l = W(K, V, lo)
1263  +a = W(K, V, hl)
1264  +b = W(K, V, hh)
1265  +okh = wb.ok(K, V, hk, hv, hl, hh, wbh)
1266  +h1 = Ord.wok_r(a, b, okh)
1267  +h2 = Ord.wok_l(a, b, okh)
1268  +pl = w_pos(K, V, lo)
1269  +pa = w_pos(K, V, hl)
1270  +pb = w_pos(K, V, hh)
1271  wb.i(K, V, hk, hv, O.OMap.bin(K, V, k, v, lo, hl), hh,
1272    Ord.rls.w1(l, a, b, h1, h2, heavy, alm, hs, pl, pa, pb),
1273    wb.i(K, V, k, v, lo, hl, Ord.rls.w0(l, a, b, h1, h2, heavy, alm, hs, pl, pa, pb), wbl,
1274      wb.l(K, V, hk, hv, hl, hh, wbh)),
1275    wb.h(K, V, hk, hv, hl, hh, wbh))
1276
1277def rld.wb(
1278  -K: Data, -V: Data, hl: O.OMap<K, V>, +k: K, +v: V, +lo: O.OMap<K, V>, +hk: K, +hv: V,
1279  +hh: O.OMap<K, V>,
1280  wbl: {WB(K, V, lo) == True{} : Bool},
1281  +wbh: {WB(K, V, O.OBin{0, hk, hv, hl, hh}) == True{} : Bool},
1282  +heavy: Ord.LE(1n+Nat.mul(3n, W(K, V, lo)), Nat.add(W(K, V, hl), W(K, V, hh))),
1283  +alm: Ord.LE(Nat.add(W(K, V, hl), W(K, V, hh)), Nat.add(3n, Nat.mul(3n, W(K, V, lo)))),
1284  +hd: Ord.LE(Nat.mul(2n, W(K, V, hh)), W(K, V, hl))
1285) -> {WB(K, V, O.OMap.rot_lo.double(K, V, k, v, lo, hk, hv, hl, hh)) == True{} : Bool}:
1286  match hl:
1287    case O.OTip{}:
1288      Empty.absurd({WB(K, V, O.OMap.rot_lo.double(K, V, k, v, lo, hk, hv, O.OTip{}, hh)) == True{} : Bool}, Ord.dtip(W(K, V, hh), hd, w_pos(K, V, hh)))
1289    case O.OBin{s, +mk, +mv, +ml, +mh}:
1290      +hl = {O.OBin{0, mk, mv, ml, mh} : O.OMap<K, V>}
1291      +l = W(K, V, lo)
1292      +x = W(K, V, ml)
1293      +y = W(K, V, mh)
1294      +b = W(K, V, hh)
1295      +okh = wb.ok(K, V, hk, hv, hl, hh, wbh)
1296      +h1 = Ord.wok_r(Nat.add(x, y), b, okh)
1297      +h2 = Ord.wok_l(Nat.add(x, y), b, okh)
1298      +wbm = wb.l(K, V, hk, hv, hl, hh, wbh)
1299      +okm = wb.ok(K, V, mk, mv, ml, mh, wbm)
1300      +h5 = Ord.wok_r(x, y, okm)
1301      +h6 = Ord.wok_l(x, y, okm)
1302      +pl = w_pos(K, V, lo)
1303      +px = w_pos(K, V, ml)
1304      +py = w_pos(K, V, mh)
1305      +pb = w_pos(K, V, hh)
1306      wb.i(K, V, mk, mv, O.OMap.bin(K, V, k, v, lo, ml), O.OMap.bin(K, V, hk, hv, mh, hh),
1307        Ord.rld.w0(l, x, y, b, h1, h2, heavy, alm, hd, h5, h6, pl, px, py, pb),
1308        wb.i(K, V, k, v, lo, ml, Ord.rld.w1(l, x, y, b, h1, h2, heavy, alm, hd, h5, h6, pl, px, py, pb),
1309          wbl, wb.l(K, V, mk, mv, ml, mh, wbm)),
1310        wb.i(K, V, hk, hv, mh, hh, Ord.rld.w2(l, x, y, b, h1, h2, heavy, alm, hd, h5, h6, pl, px, py, pb),
1311          wb.h(K, V, mk, mv, ml, mh, wbm), wb.h(K, V, hk, hv, hl, hh, wbh)))
1312
1313def rlp.wb(
1314  -K: Data, -V: Data, single: Bool, +k: K, +v: V, +lo: O.OMap<K, V>, +hk: K, +hv: V,
1315  +hl: O.OMap<K, V>, +hh: O.OMap<K, V>,
1316  es: {Nat.is_lt(W(K, V, hl), Nat.mul(2n, W(K, V, hh))) == single : Bool},
1317  wbl: {WB(K, V, lo) == True{} : Bool},
1318  wbh: {WB(K, V, O.OBin{0, hk, hv, hl, hh}) == True{} : Bool},
1319  heavy: Ord.LE(1n+Nat.mul(3n, W(K, V, lo)), Nat.add(W(K, V, hl), W(K, V, hh))),
1320  alm: Ord.LE(Nat.add(W(K, V, hl), W(K, V, hh)), Nat.add(3n, Nat.mul(3n, W(K, V, lo))))
1321) -> {WB(K, V, O.OMap.rot_lo.pick(K, V, single, k, v, lo, hk, hv, hl, hh)) == True{} : Bool}:
1322  match single:
1323    case True{}:
1324      rls.wb(K, V, k, v, lo, hk, hv, hl, hh, wbl, wbh, heavy, alm,
1325        MNat.succ_le_of_lt(W(K, V, hl), Nat.mul(2n, W(K, V, hh)), es))
1326    case False{}:
1327      rld.wb(K, V, hl, k, v, lo, hk, hv, hh, wbl, wbh, heavy, alm,
1328        MNat.le_of_not_lt(W(K, V, hl), Nat.mul(2n, W(K, V, hh)), es))
1329
1330def rl.wb(
1331  -K: Data, -V: Data, hi: O.OMap<K, V>, +k: K, +v: V, +lo: O.OMap<K, V>,
1332  wbl: {WB(K, V, lo) == True{} : Bool}, +wbh: {WB(K, V, hi) == True{} : Bool},
1333  heavy: Ord.LE(1n+Nat.mul(3n, W(K, V, lo)), W(K, V, hi)),
1334  alm: Ord.LE(W(K, V, hi), Nat.add(3n, Nat.mul(3n, W(K, V, lo))))
1335) -> {WB(K, V, Laws.g_rot_lo(K, V, k, v, lo, hi)) == True{} : Bool}:
1336  match hi:
1337    case O.OTip{}:
1338      Empty.absurd({WB(K, V, Laws.g_rot_lo(K, V, k, v, lo, O.OTip{})) == True{} : Bool}, Ord.tiph(W(K, V, lo), heavy, w_pos(K, V, lo)))
1339    case O.OBin{s, +hk, +hv, +hl, +hh}:
1340      rlp.wb(K, V, Nat.is_lt(W(K, V, hl), Nat.mul(2n, W(K, V, hh))), k, v, lo, hk, hv, hl, hh,
1341        {==}, wbl, wbh, heavy, alm)
1342
1343# Rotations toward hi, after lo grew or hi shrank by one.
1344def rhs.wb(
1345  -K: Data, -V: Data, +k: K, +v: V, +lk: K, +lv: V, +ll: O.OMap<K, V>,
1346  +lh: O.OMap<K, V>, +hi: O.OMap<K, V>,
1347  +wbl: {WB(K, V, O.OBin{0, lk, lv, ll, lh}) == True{} : Bool},
1348  wbh: {WB(K, V, hi) == True{} : Bool},
1349  +heavy: Ord.LE(1n+Nat.mul(3n, W(K, V, hi)), Nat.add(W(K, V, ll), W(K, V, lh))),
1350  +alm: Ord.LE(Nat.add(W(K, V, ll), W(K, V, lh)), Nat.add(3n, Nat.mul(3n, W(K, V, hi)))),
1351  +hs: Ord.LE(1n+W(K, V, lh), Nat.mul(2n, W(K, V, ll)))
1352) -> {WB(K, V, O.OMap.bin(K, V, lk, lv, ll, O.OMap.bin(K, V, k, v, lh, hi))) == True{} : Bool}:
1353  +l = W(K, V, hi)
1354  +a = W(K, V, lh)
1355  +b = W(K, V, ll)
1356  +okl = wb.ok(K, V, lk, lv, ll, lh, wbl)
1357  +h1 = Ord.wok_l(b, a, okl)
1358  +h2 = Ord.wok_r(b, a, okl)
1359  +pl = w_pos(K, V, hi)
1360  +pa = w_pos(K, V, lh)
1361  +pb = w_pos(K, V, ll)
1362  wb.i(K, V, lk, lv, ll, O.OMap.bin(K, V, k, v, lh, hi),
1363    Ord.rhs.w0(l, a, b, h1, h2, heavy, alm, hs, pl, pa, pb),
1364    wb.l(K, V, lk, lv, ll, lh, wbl),
1365    wb.i(K, V, k, v, lh, hi, Ord.rhs.w1(l, a, b, h1, h2, heavy, alm, hs, pl, pa, pb),
1366      wb.h(K, V, lk, lv, ll, lh, wbl), wbh))
1367
1368def rhd.wb(
1369  -K: Data, -V: Data, lh: O.OMap<K, V>, +k: K, +v: V, +lk: K, +lv: V,
1370  +ll: O.OMap<K, V>, +hi: O.OMap<K, V>,
1371  +wbl: {WB(K, V, O.OBin{0, lk, lv, ll, lh}) == True{} : Bool},
1372  wbh: {WB(K, V, hi) == True{} : Bool},
1373  +heavy: Ord.LE(1n+Nat.mul(3n, W(K, V, hi)), Nat.add(W(K, V, ll), W(K, V, lh))),
1374  +alm: Ord.LE(Nat.add(W(K, V, ll), W(K, V, lh)), Nat.add(3n, Nat.mul(3n, W(K, V, hi)))),
1375  +hd: Ord.LE(Nat.mul(2n, W(K, V, ll)), W(K, V, lh))
1376) -> {WB(K, V, O.OMap.rot_hi.double(K, V, k, v, lk, lv, ll, lh, hi)) == True{} : Bool}:
1377  match lh:
1378    case O.OTip{}:
1379      Empty.absurd({WB(K, V, O.OMap.rot_hi.double(K, V, k, v, lk, lv, ll, O.OTip{}, hi)) == True{} : Bool}, Ord.dtip(W(K, V, ll), hd, w_pos(K, V, ll)))
1380    case O.OBin{s, +mk, +mv, +ml, +mh}:
1381      +lh = {O.OBin{0, mk, mv, ml, mh} : O.OMap<K, V>}
1382      +l = W(K, V, hi)
1383      +x = W(K, V, mh)
1384      +y = W(K, V, ml)
1385      +b = W(K, V, ll)
1386      +okl = wb.ok(K, V, lk, lv, ll, lh, wbl)
1387      +h1 = Ord.wok_l(b, Nat.add(y, x), okl)
1388      +h2 = Ord.wok_r(b, Nat.add(y, x), okl)
1389      +wbm = wb.h(K, V, lk, lv, ll, lh, wbl)
1390      +okm = wb.ok(K, V, mk, mv, ml, mh, wbm)
1391      +h5 = Ord.wok_l(y, x, okm)
1392      +h6 = Ord.wok_r(y, x, okm)
1393      +pl = w_pos(K, V, hi)
1394      +px = w_pos(K, V, mh)
1395      +py = w_pos(K, V, ml)
1396      +pb = w_pos(K, V, ll)
1397      wb.i(K, V, mk, mv, O.OMap.bin(K, V, lk, lv, ll, ml), O.OMap.bin(K, V, k, v, mh, hi),
1398        Ord.rhd.w0(l, x, y, b, h1, h2, heavy, alm, hd, h5, h6, pl, px, py, pb),
1399        wb.i(K, V, lk, lv, ll, ml, Ord.rhd.w1(l, x, y, b, h1, h2, heavy, alm, hd, h5, h6, pl, px, py, pb),
1400          wb.l(K, V, lk, lv, ll, lh, wbl), wb.l(K, V, mk, mv, ml, mh, wbm)),
1401        wb.i(K, V, k, v, mh, hi, Ord.rhd.w2(l, x, y, b, h1, h2, heavy, alm, hd, h5, h6, pl, px, py, pb),
1402          wb.h(K, V, mk, mv, ml, mh, wbm), wbh))
1403
1404def rhp.wb(
1405  -K: Data, -V: Data, single: Bool, +k: K, +v: V, +lk: K, +lv: V, +ll: O.OMap<K, V>,
1406  +lh: O.OMap<K, V>, +hi: O.OMap<K, V>,
1407  es: {Nat.is_lt(W(K, V, lh), Nat.mul(2n, W(K, V, ll))) == single : Bool},
1408  wbl: {WB(K, V, O.OBin{0, lk, lv, ll, lh}) == True{} : Bool},
1409  wbh: {WB(K, V, hi) == True{} : Bool},
1410  heavy: Ord.LE(1n+Nat.mul(3n, W(K, V, hi)), Nat.add(W(K, V, ll), W(K, V, lh))),
1411  alm: Ord.LE(Nat.add(W(K, V, ll), W(K, V, lh)), Nat.add(3n, Nat.mul(3n, W(K, V, hi))))
1412) -> {WB(K, V, O.OMap.rot_hi.pick(K, V, single, k, v, lk, lv, ll, lh, hi)) == True{} : Bool}:
1413  match single:
1414    case True{}:
1415      rhs.wb(K, V, k, v, lk, lv, ll, lh, hi, wbl, wbh, heavy, alm,
1416        MNat.succ_le_of_lt(W(K, V, lh), Nat.mul(2n, W(K, V, ll)), es))
1417    case False{}:
1418      rhd.wb(K, V, lh, k, v, lk, lv, ll, hi, wbl, wbh, heavy, alm,
1419        MNat.le_of_not_lt(W(K, V, lh), Nat.mul(2n, W(K, V, ll)), es))
1420
1421def rh.wb(
1422  -K: Data, -V: Data, lo: O.OMap<K, V>, +k: K, +v: V, +hi: O.OMap<K, V>,
1423  +wbl: {WB(K, V, lo) == True{} : Bool}, wbh: {WB(K, V, hi) == True{} : Bool},
1424  heavy: Ord.LE(1n+Nat.mul(3n, W(K, V, hi)), W(K, V, lo)),
1425  alm: Ord.LE(W(K, V, lo), Nat.add(3n, Nat.mul(3n, W(K, V, hi))))
1426) -> {WB(K, V, Laws.g_rot_hi(K, V, k, v, lo, hi)) == True{} : Bool}:
1427  match lo:
1428    case O.OTip{}:
1429      Empty.absurd({WB(K, V, Laws.g_rot_hi(K, V, k, v, O.OTip{}, hi)) == True{} : Bool}, Ord.tiph(W(K, V, hi), heavy, w_pos(K, V, hi)))
1430    case O.OBin{s, +lk, +lv, +ll, +lh}:
1431      rhp.wb(K, V, Nat.is_lt(W(K, V, lh), Nat.mul(2n, W(K, V, ll))), k, v, lk, lv, ll, lh, hi,
1432        {==}, wbl, wbh, heavy, alm)
1433
1434def bif.wb(
1435  -K: Data, -V: Data, heavy_hi: Bool, heavy_lo: Bool, +k: K, +v: V,
1436  +lo: O.OMap<K, V>, +hi: O.OMap<K, V>,
1437  eh: {Laws.g_heavy_hi(K, V, lo, hi) == heavy_hi : Bool},
1438  el: {Laws.g_heavy_lo(K, V, lo, hi) == heavy_lo : Bool},
1439  wbl: {WB(K, V, lo) == True{} : Bool}, wbh: {WB(K, V, hi) == True{} : Bool},
1440  +alm: {Ord.alm(W(K, V, lo), W(K, V, hi)) == True{} : Bool}
1441) -> {WB(K, V, Laws.g_balance.if(K, V, heavy_hi, heavy_lo, k, v, lo, hi)) == True{} : Bool}:
1442  match heavy_hi heavy_lo:
1443    case True{} _:
1444      rl.wb(K, V, hi, k, v, lo, wbl, wbh,
1445        Ord.gt_le(W(K, V, hi), Nat.mul(3n, W(K, V, lo)), eh), MBool.eq_true_of_and_left(Nat.is_le(W(K, V, hi), Nat.add(3n, Nat.mul(3n, W(K, V, lo)))), Nat.is_le(W(K, V, lo), Nat.add(3n, Nat.mul(3n, W(K, V, hi)))), alm))
1446    case False{} True{}:
1447      rh.wb(K, V, lo, k, v, hi, wbl, wbh,
1448        Ord.gt_le(W(K, V, lo), Nat.mul(3n, W(K, V, hi)), el), MBool.eq_true_of_and_right(Nat.is_le(W(K, V, hi), Nat.add(3n, Nat.mul(3n, W(K, V, lo)))), Nat.is_le(W(K, V, lo), Nat.add(3n, Nat.mul(3n, W(K, V, hi)))), alm))
1449    case False{} False{}:
1450      wb.i(K, V, k, v, lo, hi,
1451        MBool.and_eq_true(Nat.is_le(W(K, V, hi), Nat.mul(3n, W(K, V, lo))), Nat.is_le(W(K, V, lo), Nat.mul(3n, W(K, V, hi))), Ord.ngt_le(W(K, V, hi), Nat.mul(3n, W(K, V, lo)), eh), Ord.ngt_le(W(K, V, lo), Nat.mul(3n, W(K, V, hi)), el)),
1452        wbl, wbh)
1453
1454def bal.wb(
1455  -K: Data, -V: Data, +k: K, +v: V, +lo: O.OMap<K, V>, +hi: O.OMap<K, V>,
1456  wbl: {WB(K, V, lo) == True{} : Bool}, wbh: {WB(K, V, hi) == True{} : Bool},
1457  alm: {Ord.alm(W(K, V, lo), W(K, V, hi)) == True{} : Bool}
1458) -> {WB(K, V, Laws.g_balance(K, V, k, v, lo, hi)) == True{} : Bool}:
1459  bif.wb(K, V, Laws.g_heavy_hi(K, V, lo, hi), Laws.g_heavy_lo(K, V, lo, hi), k, v, lo, hi,
1460    {==}, {==}, wbl, wbh, alm)
1461
1462# Balancing keeps the weight.
1463def rlp.w(
1464  -K: Data, -V: Data, single: Bool, -k: K, -v: V, +lo: O.OMap<K, V>, -hk: K, -hv: V,
1465  hl: O.OMap<K, V>, +hh: O.OMap<K, V>
1466) -> {Nat.add(W(K, V, lo), Nat.add(W(K, V, hl), W(K, V, hh)))
1467      == W(K, V, O.OMap.rot_lo.pick(K, V, single, k, v, lo, hk, hv, hl, hh)) : Nat}:
1468  match single hl:
1469    case True{} +hl:
1470      Ord.sy(Nat.add(Nat.add(W(K, V, lo), W(K, V, hl)), W(K, V, hh)),
1471        Nat.add(W(K, V, lo), Nat.add(W(K, V, hl), W(K, V, hh))),
1472        MNat.add_assoc(W(K, V, lo), W(K, V, hl), W(K, V, hh)))
1473    case False{} O.OTip{}:
1474      Ord.sy(Nat.add(Nat.add(W(K, V, lo), 1n), W(K, V, hh)), Nat.add(W(K, V, lo), Nat.add(1n, W(K, V, hh))),
1475        MNat.add_assoc(W(K, V, lo), 1n, W(K, V, hh)))
1476    case False{} O.OBin{s, mk, mv, +ml, +mh}:
1477      +l = W(K, V, lo)
1478      +x = W(K, V, ml)
1479      +y = W(K, V, mh)
1480      +b = W(K, V, hh)
1481      Ord.tr(Nat.add(l, Nat.add(Nat.add(x, y), b)), Nat.add(l, Nat.add(x, Nat.add(y, b))),
1482        Nat.add(Nat.add(l, x), Nat.add(y, b)),
1483        Ord.cong_add(l, l, Nat.add(Nat.add(x, y), b), Nat.add(x, Nat.add(y, b)), {==}, MNat.add_assoc(x, y, b)),
1484        Ord.sy(Nat.add(Nat.add(l, x), Nat.add(y, b)), Nat.add(l, Nat.add(x, Nat.add(y, b))),
1485          MNat.add_assoc(l, x, Nat.add(y, b))))
1486
1487def rhp.w(
1488  -K: Data, -V: Data, single: Bool, -k: K, -v: V, -lk: K, -lv: V, +ll: O.OMap<K, V>,
1489  lh: O.OMap<K, V>, +hi: O.OMap<K, V>
1490) -> {Nat.add(Nat.add(W(K, V, ll), W(K, V, lh)), W(K, V, hi))
1491      == W(K, V, O.OMap.rot_hi.pick(K, V, single, k, v, lk, lv, ll, lh, hi)) : Nat}:
1492  match single lh:
1493    case True{} +lh:
1494      MNat.add_assoc(W(K, V, ll), W(K, V, lh), W(K, V, hi))
1495    case False{} O.OTip{}:
1496      MNat.add_assoc(W(K, V, ll), 1n, W(K, V, hi))
1497    case False{} O.OBin{s, mk, mv, +ml, +mh}:
1498      +l = W(K, V, hi)
1499      +x = W(K, V, mh)
1500      +y = W(K, V, ml)
1501      +b = W(K, V, ll)
1502      Ord.tr(Nat.add(Nat.add(b, Nat.add(y, x)), l), Nat.add(Nat.add(Nat.add(b, y), x), l),
1503        Nat.add(Nat.add(b, y), Nat.add(x, l)),
1504        Ord.cong_add(Nat.add(b, Nat.add(y, x)), Nat.add(Nat.add(b, y), x), l, l,
1505          Ord.sy(Nat.add(Nat.add(b, y), x), Nat.add(b, Nat.add(y, x)), MNat.add_assoc(b, y, x)), {==}),
1506        MNat.add_assoc(Nat.add(b, y), x, l))
1507
1508def rl.w(-K: Data, -V: Data, hi: O.OMap<K, V>, -k: K, -v: V, +lo: O.OMap<K, V>)
1509  -> {Nat.add(W(K, V, lo), W(K, V, hi)) == W(K, V, Laws.g_rot_lo(K, V, k, v, lo, hi)) : Nat}:
1510  match hi:
1511    case O.OTip{}:
1512      {==}
1513    case O.OBin{s, hk, hv, +hl, +hh}:
1514      rlp.w(K, V, Nat.is_lt(W(K, V, hl), Nat.mul(2n, W(K, V, hh))), k, v, lo, hk, hv, hl, hh)
1515
1516def rh.w(-K: Data, -V: Data, lo: O.OMap<K, V>, -k: K, -v: V, +hi: O.OMap<K, V>)
1517  -> {Nat.add(W(K, V, lo), W(K, V, hi)) == W(K, V, Laws.g_rot_hi(K, V, k, v, lo, hi)) : Nat}:
1518  match lo:
1519    case O.OTip{}:
1520      {==}
1521    case O.OBin{s, lk, lv, +ll, +lh}:
1522      rhp.w(K, V, Nat.is_lt(W(K, V, lh), Nat.mul(2n, W(K, V, ll))), k, v, lk, lv, ll, lh, hi)
1523
1524def bif.w(
1525  -K: Data, -V: Data, heavy_hi: Bool, heavy_lo: Bool, -k: K, -v: V,
1526  +lo: O.OMap<K, V>, +hi: O.OMap<K, V>
1527) -> {Nat.add(W(K, V, lo), W(K, V, hi))
1528      == W(K, V, Laws.g_balance.if(K, V, heavy_hi, heavy_lo, k, v, lo, hi)) : Nat}:
1529  match heavy_hi heavy_lo:
1530    case True{} _:
1531      rl.w(K, V, hi, k, v, lo)
1532    case False{} True{}:
1533      rh.w(K, V, lo, k, v, hi)
1534    case False{} False{}:
1535      {==}
1536
1537def bal.w(-K: Data, -V: Data, -k: K, -v: V, +lo: O.OMap<K, V>, +hi: O.OMap<K, V>)
1538  -> {Nat.add(W(K, V, lo), W(K, V, hi)) == W(K, V, Laws.g_balance(K, V, k, v, lo, hi)) : Nat}:
1539  bif.w(K, V, Laws.g_heavy_hi(K, V, lo, hi), Laws.g_heavy_lo(K, V, lo, hi), k, v, lo, hi)
1540
1541def bal.lo.near(
1542  -K: Data, -V: Data, -k: K, -v: V, +lo: O.OMap<K, V>, +lo2: O.OMap<K, V>, +hi: O.OMap<K, V>,
1543  n1: Ord.LE(W(K, V, lo), 1n+W(K, V, lo2)), n2: Ord.LE(W(K, V, lo2), 1n+W(K, V, lo))
1544) -> {Ord.near(Nat.add(W(K, V, lo), W(K, V, hi)), W(K, V, Laws.g_balance(K, V, k, v, lo2, hi))) == True{} : Bool}:
1545  %bal.w(K, V, k, v, lo2, hi) : {Ord.near(Nat.add(W(K, V, lo), W(K, V, hi)), _) == True{} : Bool}
1546  Ord.nearlo.w0(W(K, V, lo), W(K, V, lo2), W(K, V, hi), n1, n2)
1547
1548def bal.hi.near(
1549  -K: Data, -V: Data, -k: K, -v: V, +lo: O.OMap<K, V>, +hi: O.OMap<K, V>, +hi2: O.OMap<K, V>,
1550  n1: Ord.LE(W(K, V, hi), 1n+W(K, V, hi2)), n2: Ord.LE(W(K, V, hi2), 1n+W(K, V, hi))
1551) -> {Ord.near(Nat.add(W(K, V, lo), W(K, V, hi)), W(K, V, Laws.g_balance(K, V, k, v, lo, hi2))) == True{} : Bool}:
1552  %bal.w(K, V, k, v, lo, hi2) : {Ord.near(Nat.add(W(K, V, lo), W(K, V, hi)), _) == True{} : Bool}
1553  Ord.nearhi.w0(W(K, V, lo), W(K, V, hi), W(K, V, hi2), n1, n2)
1554
1555# lo became lo2, one lighter or heavier at most: rebalance the node.
1556def bal.lo(
1557  -K: Data, -V: Data, +k: K, +v: V, +lo: O.OMap<K, V>, +lo2: O.OMap<K, V>, +hi: O.OMap<K, V>,
1558  +ok: {Laws.weight_ok(W(K, V, lo), W(K, V, hi)) == True{} : Bool},
1559  wbh: {WB(K, V, hi) == True{} : Bool},
1560  +pw: {PW(K, V, W(K, V, lo), lo2) == True{} : Bool}
1561) -> {PW(K, V, Nat.add(W(K, V, lo), W(K, V, hi)), Laws.g_balance(K, V, k, v, lo2, hi)) == True{} : Bool}:
1562  +a = W(K, V, lo)
1563  +a2 = W(K, V, lo2)
1564  +c = W(K, V, hi)
1565  +nr = MBool.eq_true_of_and_right(WB(K, V, lo2), Ord.near(a, a2), pw)
1566  +n1 = MBool.eq_true_of_and_left(Nat.is_le(a, 1n+a2), Nat.is_le(a2, 1n+a), nr)
1567  +n2 = MBool.eq_true_of_and_right(Nat.is_le(a, 1n+a2), Nat.is_le(a2, 1n+a), nr)
1568  MBool.and_eq_true(WB(K, V, Laws.g_balance(K, V, k, v, lo2, hi)), Ord.near(Nat.add(a, c), W(K, V, Laws.g_balance(K, V, k, v, lo2, hi))), bal.wb(K, V, k, v, lo2, hi, MBool.eq_true_of_and_left(WB(K, V, lo2), Ord.near(a, a2), pw), wbh,
1569      Ord.almlo.w0(a, c, a2, Ord.wok_l(a, c, ok), Ord.wok_r(a, c, ok), n1, n2)), bal.lo.near(K, V, k, v, lo, lo2, hi, n1, n2))
1570
1571def bal.hi(
1572  -K: Data, -V: Data, +k: K, +v: V, +lo: O.OMap<K, V>, +hi: O.OMap<K, V>, +hi2: O.OMap<K, V>,
1573  +ok: {Laws.weight_ok(W(K, V, lo), W(K, V, hi)) == True{} : Bool},
1574  wbl: {WB(K, V, lo) == True{} : Bool},
1575  +pw: {PW(K, V, W(K, V, hi), hi2) == True{} : Bool}
1576) -> {PW(K, V, Nat.add(W(K, V, lo), W(K, V, hi)), Laws.g_balance(K, V, k, v, lo, hi2)) == True{} : Bool}:
1577  +a = W(K, V, lo)
1578  +c = W(K, V, hi)
1579  +c2 = W(K, V, hi2)
1580  +nr = MBool.eq_true_of_and_right(WB(K, V, hi2), Ord.near(c, c2), pw)
1581  +n1 = MBool.eq_true_of_and_left(Nat.is_le(c, 1n+c2), Nat.is_le(c2, 1n+c), nr)
1582  +n2 = MBool.eq_true_of_and_right(Nat.is_le(c, 1n+c2), Nat.is_le(c2, 1n+c), nr)
1583  MBool.and_eq_true(WB(K, V, Laws.g_balance(K, V, k, v, lo, hi2)), Ord.near(Nat.add(a, c), W(K, V, Laws.g_balance(K, V, k, v, lo, hi2))), bal.wb(K, V, k, v, lo, hi2, wbl, MBool.eq_true_of_and_left(WB(K, V, hi2), Ord.near(c, c2), pw),
1584      Ord.almhi.w0(a, c, c2, Ord.wok_l(a, c, ok), Ord.wok_r(a, c, ok), n1, n2)), bal.hi.near(K, V, k, v, lo, hi, hi2, n1, n2))
1585
1586def put.wb(
1587  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, t: O.OMap<K, V>, +k: K, +v: V,
1588  +wb: {WB(K, V, t) == True{} : Bool}
1589) -> {PW(K, V, W(K, V, t), Laws.g_put(~K, ~V, ~cmp, t, k, v)) == True{} : Bool}:
1590  match t:
1591    case O.OTip{}:
1592      {==}
1593    case O.OBin{+s, +key, +val, +lo, +hi}:
1594      +ok = wb.ok(K, V, key, val, lo, hi, wb)
1595      +wbl = wb.l(K, V, key, val, lo, hi, wb)
1596      +wbh = wb.h(K, V, key, val, lo, hi, wb)
1597      +n = Nat.add(W(K, V, lo), W(K, V, hi))
1598      cmp.split(O.OMap<K, V>, Bool, x => PW(K, V, n, x), True{}, cmp(k, key),
1599        u => Laws.g_balance(K, V, key, val, Laws.g_put(~K, ~V, ~cmp, lo, k, v), hi),
1600        u => O.OBin{s, key, v, lo, hi},
1601        u => Laws.g_balance(K, V, key, val, lo, Laws.g_put(~K, ~V, ~cmp, hi, k, v)),
1602        e => bal.lo(K, V, key, val, lo, Laws.g_put(~K, ~V, ~cmp, lo, k, v), hi, ok, wbh,
1603          put.wb(~K, ~V, ~cmp, lo, k, v, wbl)),
1604        e => MBool.and_eq_true(WB(K, V, O.OBin{s, key, v, lo, hi}), Ord.near(n, n), wb, Ord.nearrf.w0(n)),
1605        e => bal.hi(K, V, key, val, lo, hi, Laws.g_put(~K, ~V, ~cmp, hi, k, v), ok, wbl,
1606          put.wb(~K, ~V, ~cmp, hi, k, v, wbh)))
1607
1608def Laws.omap_put_weight_balanced(K, V, cmp, m, wb, k, v):
1609  MBool.eq_true_of_and_left(WB(K, V, Laws.g_put(~K, ~V, ~cmp, m, k, v)), Ord.near(W(K, V, m), W(K, V, Laws.g_put(~K, ~V, ~cmp, m, k, v))), put.wb(~K, ~V, ~cmp, m, k, v, wb))
1610
1611def pm.fin.wb.go(
1612  -K: Data, -V: Data, +mk: K, +mv: V, +t: O.OMap<K, V>, +k: K, +v: V,
1613  +lo: O.OMap<K, V>, +hi: O.OMap<K, V>,
1614  ok: {Laws.weight_ok(W(K, V, lo), W(K, V, hi)) == True{} : Bool},
1615  wbh: {WB(K, V, hi) == True{} : Bool},
1616  ih: {PMW(K, V, W(K, V, lo), {(mk, mv, t) : K & V & O.OMap<K, V>}) == True{} : Bool}
1617) -> {PMW(K, V, Nat.add(W(K, V, lo), W(K, V, hi)),
1618       Laws.g_pop_min.fin(K, V, k, v, hi, {(mk, mv, t) : K & V & O.OMap<K, V>})) == True{} : Bool}:
1619  bal.lo(K, V, k, v, lo, t, hi, ok, wbh, ih)
1620
1621# Workaround for https://github.com/bendlang/bend/issues/1077: bind the tuple without +.
1622def pm.fin.wb(
1623  -K: Data, -V: Data, r: K & V & O.OMap<K, V>, +k: K, +v: V,
1624  +lo: O.OMap<K, V>, +hi: O.OMap<K, V>,
1625  ok: {Laws.weight_ok(W(K, V, lo), W(K, V, hi)) == True{} : Bool},
1626  wbh: {WB(K, V, hi) == True{} : Bool},
1627  ih: {PMW(K, V, W(K, V, lo), r) == True{} : Bool}
1628) -> {PMW(K, V, Nat.add(W(K, V, lo), W(K, V, hi)), Laws.g_pop_min.fin(K, V, k, v, hi, r)) == True{} : Bool}:
1629  (mk, rest) = r
1630  (mv, t) = rest
1631  pm.fin.wb.go(K, V, mk, mv, t, k, v, lo, hi, ok, wbh, ih)
1632
1633def pm.wb(
1634  -K: Data, -V: Data, lo: O.OMap<K, V>, +k: K, +v: V, +hi: O.OMap<K, V>,
1635  +e: {WB(K, V, O.OBin{0, k, v, lo, hi}) == True{} : Bool}
1636) -> {PMW(K, V, Nat.add(W(K, V, lo), W(K, V, hi)), Laws.g_pop_min(K, V, lo, k, v, hi)) == True{} : Bool}:
1637  match lo:
1638    case O.OTip{}:
1639      MBool.and_eq_true(WB(K, V, hi), Ord.near(1n+W(K, V, hi), W(K, V, hi)), wb.h(K, V, k, v, O.OTip{}, hi, e), Ord.nearpm.w0(W(K, V, hi)))
1640    case O.OBin{s, +lk, +lv, +ll, +lh}:
1641      +lo = {O.OBin{0, lk, lv, ll, lh} : O.OMap<K, V>}
1642      pm.fin.wb(K, V, Laws.g_pop_min(K, V, ll, lk, lv, lh), k, v, lo, hi,
1643        wb.ok(K, V, k, v, lo, hi, e), wb.h(K, V, k, v, lo, hi, e),
1644        pm.wb(K, V, ll, lk, lv, lh, wb.l(K, V, k, v, lo, hi, e)))
1645
1646def glue.fin.wb.go(
1647  -K: Data, -V: Data, +mk: K, +mv: V, +t: O.OMap<K, V>, +lo: O.OMap<K, V>, +hi: O.OMap<K, V>,
1648  ok: {Laws.weight_ok(W(K, V, lo), W(K, V, hi)) == True{} : Bool},
1649  wbl: {WB(K, V, lo) == True{} : Bool},
1650  pmr: {PMW(K, V, W(K, V, hi), {(mk, mv, t) : K & V & O.OMap<K, V>}) == True{} : Bool}
1651) -> {PW(K, V, Nat.add(W(K, V, lo), W(K, V, hi)),
1652       Laws.g_glue.fin(K, V, lo, {(mk, mv, t) : K & V & O.OMap<K, V>})) == True{} : Bool}:
1653  bal.hi(K, V, mk, mv, lo, hi, t, ok, wbl, pmr)
1654
1655# Workaround for https://github.com/bendlang/bend/issues/1077: bind the tuple without +.
1656def glue.fin.wb(
1657  -K: Data, -V: Data, r: K & V & O.OMap<K, V>, +lo: O.OMap<K, V>, +hi: O.OMap<K, V>,
1658  ok: {Laws.weight_ok(W(K, V, lo), W(K, V, hi)) == True{} : Bool},
1659  wbl: {WB(K, V, lo) == True{} : Bool},
1660  pmr: {PMW(K, V, W(K, V, hi), r) == True{} : Bool}
1661) -> {PW(K, V, Nat.add(W(K, V, lo), W(K, V, hi)), Laws.g_glue.fin(K, V, lo, r)) == True{} : Bool}:
1662  (mk, rest) = r
1663  (mv, t) = rest
1664  glue.fin.wb.go(K, V, mk, mv, t, lo, hi, ok, wbl, pmr)
1665
1666def glue.wb(
1667  -K: Data, -V: Data, hi: O.OMap<K, V>, +lo: O.OMap<K, V>, -key: K, -val: V,
1668  +e: {WB(K, V, O.OBin{0, key, val, lo, hi}) == True{} : Bool}
1669) -> {PW(K, V, Nat.add(W(K, V, lo), W(K, V, hi)), Laws.g_glue(K, V, lo, hi)) == True{} : Bool}:
1670  match hi:
1671    case O.OTip{}:
1672      MBool.and_eq_true(WB(K, V, lo), Ord.near(Nat.add(W(K, V, lo), 1n), W(K, V, lo)), wb.l(K, V, key, val, lo, O.OTip{}, e), Ord.neargt.w0(W(K, V, lo)))
1673    case O.OBin{s, +k, +v, +hl, +hh}:
1674      +hi = {O.OBin{0, k, v, hl, hh} : O.OMap<K, V>}
1675      glue.fin.wb(K, V, Laws.g_pop_min(K, V, hl, k, v, hh), lo, hi,
1676        wb.ok(K, V, key, val, lo, hi, e), wb.l(K, V, key, val, lo, hi, e),
1677        pm.wb(K, V, hl, k, v, hh, wb.h(K, V, key, val, lo, hi, e)))
1678
1679def del.wb(
1680  ~K: Data, ~V: Data, ~cmp: K -> K -> Cmp, t: O.OMap<K, V>, +k: K,
1681  +wb: {WB(K, V, t) == True{} : Bool}
1682) -> {PW(K, V, W(K, V, t), Laws.g_del(~K, ~V, ~cmp, t, k)) == True{} : Bool}:
1683  match t:
1684    case O.OTip{}:
1685      {==}
1686    case O.OBin{+s, +key, +val, +lo, +hi}:
1687      +ok = wb.ok(K, V, key, val, lo, hi, wb)
1688      +wbl = wb.l(K, V, key, val, lo, hi, wb)
1689      +wbh = wb.h(K, V, key, val, lo, hi, wb)
1690      +n = Nat.add(W(K, V, lo), W(K, V, hi))
1691      cmp.split(O.OMap<K, V>, Bool, x => PW(K, V, n, x), True{}, cmp(k, key),
1692        u => Laws.g_balance(K, V, key, val, Laws.g_del(~K, ~V, ~cmp, lo, k), hi),
1693        u => Laws.g_glue(K, V, lo, hi),
1694        u => Laws.g_balance(K, V, key, val, lo, Laws.g_del(~K, ~V, ~cmp, hi, k)),
1695        e => bal.lo(K, V, key, val, lo, Laws.g_del(~K, ~V, ~cmp, lo, k), hi, ok, wbh,
1696          del.wb(~K, ~V, ~cmp, lo, k, wbl)),
1697        e => glue.wb(K, V, hi, lo, key, val, wb),
1698        e => bal.hi(K, V, key, val, lo, hi, Laws.g_del(~K, ~V, ~cmp, hi, k), ok, wbl,
1699          del.wb(~K, ~V, ~cmp, hi, k, wbh)))
1700
1701def Laws.omap_del_weight_balanced(K, V, cmp, m, wb, k):
1702  MBool.eq_true_of_and_left(WB(K, V, Laws.g_del(~K, ~V, ~cmp, m, k)), Ord.near(W(K, V, m), W(K, V, Laws.g_del(~K, ~V, ~cmp, m, k))), del.wb(~K, ~V, ~cmp, m, k, wb))
1703
1704def Laws.omap_g_put_matches():
1705  {==}
1706
1707def Laws.omap_g_del_matches():
1708  {==}
1709
1710def Laws.hmap_get_put():
1711  {==}
1712
1713def Laws.hmap_get_put_other():
1714  {==}
1715
1716def Laws.hmap_collision():
1717  {==}
1718
1719def Laws.hmap_replace_collision():
1720  {==}
1721
1722def Laws.hmap_high_bit():
1723  {==}
1724
1725def Laws.hmap_missing_collision():
1726  {==}
1727
1728# --- hmap ------------------------------------------------------------------------
1729
1730def h.sb(-a: Bool, -b: Bool, e: {a == b : Bool}) -> {b == a : Bool}:
1731  Equal.sym(Bool, a, b, e)
1732
1733def h.tf(-A: Type, -b: Bool, et: {b == True{} : Bool}, ef: {b == False{} : Bool}) -> A:
1734  Empty.absurd(A, MBool.false_ne_true()(Equal.trans(Bool, False{}, b, True{}, Equal.sym(Bool, b, False{}, ef), et)))
1735
1736def h.isS(-V: Data, m: Maybe<&2, V>) -> Type:
1737  match m:
1738    case None{}:
1739      Empty
1740    case Some{x}:
1741      Unit
1742
1743def h.some_none.e(-V: Data, -x: V, e: {Some{x} == None{} : Maybe<&2, V>}) -> Empty:
1744  %e : h.isS(V, _)
1745  Unit{}
1746
1747def h.some_none(-A: Type, -V: Data, -x: V, e: {Some{x} == None{} : Maybe<&2, V>}) -> A:
1748  Empty.absurd(A, h.some_none.e(V, x, e))
1749
1750def h.none_some(-A: Type, -V: Data, -x: V, e: {None{} == Some{x} : Maybe<&2, V>}) -> A:
1751  Empty.absurd(A, h.some_none.e(V, x, Equal.sym(Maybe<&2, V>, None{}, Some{x}, e)))
1752
1753# U32 equality is Word equality, so is_eq is reflexive and sound.
1754def h.wcmp_refl(n: Nat, w: Word(n)) -> {Word.cmp(n, w, w) == EQ{} : Cmp}:
1755  match n:
1756    case 0n:
1757      {==}
1758    case 1n+p:
1759      match w:
1760        case WCon{+b, +t}:
1761          %Equal.sym(Cmp, Word.cmp(p, t, t), EQ{}, h.wcmp_refl(p, t)) : {Word.cmp.fin(b, b, _) == EQ{} : Cmp}
1762          MBool.cmp_refl(b)
1763
1764def h.u_refl(x: U32) -> {U32.is_eq(x, x) == True{} : Bool}:
1765  match x:
1766    case U32{+w}:
1767      %Equal.sym(Cmp, Word.cmp(32n, w, w), EQ{}, h.wcmp_refl(32n, w)) : {Cmp.is_eq(_) == True{} : Bool}
1768      {==}
1769
1770def h.fin_eq(t: Cmp, -x: Bool, -y: Bool, e: {Cmp.is_eq(Word.cmp.fin(x, y, t)) == True{} : Bool})
1771  -> {Cmp.is_eq(t) == True{} : Bool}:
1772  match t:
1773    case LT{}:
1774      Empty.absurd({Cmp.is_eq(LT{}) == True{} : Bool}, MBool.false_ne_true()(e))
1775    case EQ{}:
1776      {==}
1777    case GT{}:
1778      Empty.absurd({Cmp.is_eq(GT{}) == True{} : Bool}, MBool.false_ne_true()(e))
1779
1780def h.fin_hd(t: Cmp, x: Bool, y: Bool, e: {Cmp.is_eq(Word.cmp.fin(x, y, t)) == True{} : Bool})
1781  -> {x == y : Bool}:
1782  match t:
1783    case LT{}:
1784      Empty.absurd({x == y : Bool}, MBool.false_ne_true()(e))
1785    case EQ{}:
1786      match x y:
1787        case False{} False{}:
1788          {==}
1789        case False{} True{}:
1790          Empty.absurd({False{} == True{} : Bool}, MBool.false_ne_true()(e))
1791        case True{} False{}:
1792          Empty.absurd({True{} == False{} : Bool}, MBool.false_ne_true()(e))
1793        case True{} True{}:
1794          {==}
1795    case GT{}:
1796      Empty.absurd({x == y : Bool}, MBool.false_ne_true()(e))
1797
1798def h.wcmp_sound(+n: Nat, a: Word(n), b: Word(n), +e: {Cmp.is_eq(Word.cmp(n, a, b)) == True{} : Bool})
1799  -> {a == b : Word(n)}:
1800  match n:
1801    case 0n:
1802      match a b:
1803        case WNil{} WNil{}:
1804          {==}
1805    case 1n+p:
1806      match a b:
1807        case WCon{+x, +at} WCon{+y, +bt}:
1808          +e1 = h.fin_hd(Word.cmp(p, at, bt), x, y, e)
1809          +e2 = h.wcmp_sound(p, at, bt, h.fin_eq(Word.cmp(p, at, bt), x, y, e))
1810          %e1 : {WCon{x, at} == WCon{_, bt} : Word(1n+p)}
1811          %e2 : {WCon{x, at} == WCon{x, _} : Word(1n+p)}
1812          {==}
1813
1814def h.u_sound(a: U32, b: U32, e: {U32.is_eq(a, b) == True{} : Bool}) -> {a == b : U32}:
1815  match a b:
1816    case U32{+x} U32{+y}:
1817      %h.wcmp_sound(32n, x, y, e) : {U32{x} == U32{_} : U32}
1818      {==}
1819
1820# A mask with at most one set bit routes every hash to one of two sides.
1821def h.isz(n: Nat, w: Word(n)) -> Bool:
1822  match n:
1823    case 0n:
1824      True{}
1825    case 1n+p:
1826      match w:
1827        case WCon{b, t}:
1828          Bool.not(b) && h.isz(p, t)
1829
1830def h.at1(n: Nat, w: Word(n)) -> Bool:
1831  match n:
1832    case 0n:
1833      True{}
1834    case 1n+p:
1835      match w:
1836        case WCon{b, t}:
1837          match b:
1838            case True{}:
1839              h.isz(p, t)
1840            case False{}:
1841              h.at1(p, t)
1842
1843def h.onebit(m: U32) -> Bool:
1844  match m:
1845    case U32{w}:
1846      h.at1(32n, w)
1847
1848def h.and_z(+n: Nat, x: Word(n), m: Word(n), e: {h.isz(n, m) == True{} : Bool})
1849  -> {Word.and(n, x, m) == Word.zero(n) : Word(n)}:
1850  match n:
1851    case 0n:
1852      match x m:
1853        case WNil{} WNil{}:
1854          {==}
1855    case 1n+p:
1856      match x m:
1857        case WCon{+a, +xt} WCon{True{}, +mt}:
1858          Empty.absurd({Word.and(1n+p, WCon{a, xt}, WCon{True{}, mt}) == Word.zero(1n+p) : Word(1n+p)}, MBool.false_ne_true()(e))
1859        case WCon{True{}, +xt} WCon{False{}, +mt}:
1860          Equal.cong(Word(p), Word(1n+p), w => WCon{False{}, w}, Word.and(p, xt, mt), Word.zero(p),
1861            h.and_z(p, xt, mt, e))
1862        case WCon{False{}, +xt} WCon{False{}, +mt}:
1863          Equal.cong(Word(p), Word(1n+p), w => WCon{False{}, w}, Word.and(p, xt, mt), Word.zero(p),
1864            h.and_z(p, xt, mt, e))
1865
1866def h.zc(+n: Nat, +x: Word(n), +m: Word(n), +e: {h.isz(n, m) == True{} : Bool})
1867  -> {Word.cmp(n, Word.and(n, x, m), Word.zero(n)) == EQ{} : Cmp}:
1868  %Equal.sym(Word(n), Word.and(n, x, m), Word.zero(n), h.and_z(n, x, m, e)) : {Word.cmp(n, _, Word.zero(n)) == EQ{} : Cmp}
1869  h.wcmp_refl(n, Word.zero(n))
1870
1871def h.zc2(+n: Nat, +x: Word(n), +y: Word(n), +m: Word(n), +e: {h.isz(n, m) == True{} : Bool})
1872  -> {Word.cmp(n, Word.and(n, x, m), Word.and(n, y, m)) == EQ{} : Cmp}:
1873  %Equal.sym(Word(n), Word.and(n, x, m), Word.zero(n), h.and_z(n, x, m, e)) : {Word.cmp(n, _, Word.and(n, y, m)) == EQ{} : Cmp}
1874  %Equal.sym(Word(n), Word.and(n, y, m), Word.zero(n), h.and_z(n, y, m, e)) : {Word.cmp(n, Word.zero(n), _) == EQ{} : Cmp}
1875  h.wcmp_refl(n, Word.zero(n))
1876
1877# A head bit under a set mask bit, with the rest masked to zero, is set when the word is not zero.
1878def h.hd_true(
1879  a: Bool, +p: Nat, +xt: Word(p), +mt: Word(p), +em: {h.isz(p, mt) == True{} : Bool},
1880  ex: {Cmp.is_eq(Word.cmp.fin(Bool.and(a, True{}), False{}, Word.cmp(p, Word.and(p, xt, mt), Word.zero(p)))) == False{} : Bool}
1881) -> {a == True{} : Bool}:
1882  match a:
1883    case True{}:
1884      {==}
1885    case False{}:
1886      Equal.sym(Bool, True{}, False{},
1887        rw(Cmp, t => {Cmp.is_eq(Word.cmp.fin(False{}, False{}, t)) == False{} : Bool},
1888          EQ{}, Word.cmp(p, Word.and(p, xt, mt), Word.zero(p)),
1889          Equal.sym(Cmp, Word.cmp(p, Word.and(p, xt, mt), Word.zero(p)), EQ{}, h.zc(p, xt, mt, em)), ex))
1890
1891def h.low(a: Bool, t: Cmp, e: {Cmp.is_eq(Word.cmp.fin(Bool.and(a, False{}), False{}, t)) == False{} : Bool})
1892  -> {Cmp.is_eq(t) == False{} : Bool}:
1893  match a:
1894    case True{}:
1895      match t:
1896        case LT{}:
1897          e
1898        case EQ{}:
1899          e
1900        case GT{}:
1901          e
1902    case False{}:
1903      match t:
1904        case LT{}:
1905          e
1906        case EQ{}:
1907          e
1908        case GT{}:
1909          e
1910
1911def h.lift0(t: Cmp, ih: {Cmp.is_eq(t) == True{} : Bool})
1912  -> {Cmp.is_eq(Word.cmp.fin(False{}, False{}, t)) == True{} : Bool}:
1913  match t:
1914    case LT{}:
1915      ih
1916    case EQ{}:
1917      {==}
1918    case GT{}:
1919      ih
1920
1921def h.lift(a: Bool, c: Bool, t: Cmp, ih: {Cmp.is_eq(t) == True{} : Bool})
1922  -> {Cmp.is_eq(Word.cmp.fin(Bool.and(a, False{}), Bool.and(c, False{}), t)) == True{} : Bool}:
1923  match a c:
1924    case True{} True{}:
1925      h.lift0(t, ih)
1926    case True{} False{}:
1927      h.lift0(t, ih)
1928    case False{} True{}:
1929      h.lift0(t, ih)
1930    case False{} False{}:
1931      h.lift0(t, ih)
1932
1933def h.route_t(
1934  +a: Bool, +c: Bool, +p: Nat, +xt: Word(p), +yt: Word(p), +mt: Word(p),
1935  +em: {h.isz(p, mt) == True{} : Bool},
1936  ex: {Cmp.is_eq(Word.cmp.fin(Bool.and(a, True{}), False{}, Word.cmp(p, Word.and(p, xt, mt), Word.zero(p)))) == False{} : Bool},
1937  ey: {Cmp.is_eq(Word.cmp.fin(Bool.and(c, True{}), False{}, Word.cmp(p, Word.and(p, yt, mt), Word.zero(p)))) == False{} : Bool}
1938) -> {Cmp.is_eq(Word.cmp.fin(Bool.and(a, True{}), Bool.and(c, True{}),
1939       Word.cmp(p, Word.and(p, xt, mt), Word.and(p, yt, mt)))) == True{} : Bool}:
1940  %Equal.sym(Bool, a, True{}, h.hd_true(a, p, xt, mt, em, ex))
1941    : {Cmp.is_eq(Word.cmp.fin(Bool.and(_, True{}), Bool.and(c, True{}), Word.cmp(p, Word.and(p, xt, mt), Word.and(p, yt, mt)))) == True{} : Bool}
1942  %Equal.sym(Bool, c, True{}, h.hd_true(c, p, yt, mt, em, ey))
1943    : {Cmp.is_eq(Word.cmp.fin(True{}, Bool.and(_, True{}), Word.cmp(p, Word.and(p, xt, mt), Word.and(p, yt, mt)))) == True{} : Bool}
1944  %Equal.sym(Cmp, Word.cmp(p, Word.and(p, xt, mt), Word.and(p, yt, mt)), EQ{}, h.zc2(p, xt, yt, mt, em))
1945    : {Cmp.is_eq(Word.cmp.fin(True{}, True{}, _)) == True{} : Bool}
1946  {==}
1947
1948def h.route_w(
1949  +n: Nat, x: Word(n), y: Word(n), m: Word(n),
1950  em: {h.at1(n, m) == True{} : Bool},
1951  ex: {Cmp.is_eq(Word.cmp(n, Word.and(n, x, m), Word.zero(n))) == False{} : Bool},
1952  ey: {Cmp.is_eq(Word.cmp(n, Word.and(n, y, m), Word.zero(n))) == False{} : Bool}
1953) -> {Cmp.is_eq(Word.cmp(n, Word.and(n, x, m), Word.and(n, y, m))) == True{} : Bool}:
1954  match n:
1955    case 0n:
1956      {==}
1957    case 1n+p:
1958      match x y m:
1959        case WCon{+a, +xt} WCon{+c, +yt} WCon{True{}, +mt}:
1960          h.route_t(a, c, p, xt, yt, mt, em, ex, ey)
1961        case WCon{+a, +xt} WCon{+c, +yt} WCon{False{}, +mt}:
1962          h.lift(a, c, Word.cmp(p, Word.and(p, xt, mt), Word.and(p, yt, mt)),
1963            h.route_w(p, xt, yt, mt, em,
1964              h.low(a, Word.cmp(p, Word.and(p, xt, mt), Word.zero(p)), ex),
1965              h.low(c, Word.cmp(p, Word.and(p, yt, mt), Word.zero(p)), ey)))
1966
1967def h.route(
1968  x: U32, y: U32, m: U32, em: {h.onebit(m) == True{} : Bool},
1969  ex: {U32.is_eq((x .&. m : U32), 0) == False{} : Bool},
1970  ey: {U32.is_eq((y .&. m : U32), 0) == False{} : Bool}
1971) -> {U32.is_eq((x .&. m : U32), (y .&. m : U32)) == True{} : Bool}:
1972  match x y m:
1973    case U32{xw} U32{yw} U32{+mw}:
1974      h.route_w(32n, xw, yw, mw, em, ex, ey)
1975
1976def h.isz_put(n: Nat, t: Word(n), e: {h.isz(n, t) == True{} : Bool})
1977  -> {h.isz(n, Word.shl.put(n, False{}, t)) == True{} : Bool}:
1978  match n:
1979    case 0n:
1980      {==}
1981    case 1n+p:
1982      match t:
1983        case WCon{True{}, t2}:
1984          Empty.absurd({h.isz(1n+p, Word.shl.put(1n+p, False{}, WCon{True{}, t2})) == True{} : Bool}, MBool.false_ne_true()(e))
1985        case WCon{False{}, t2}:
1986          h.isz_put(p, t2, e)
1987
1988def h.at1_put.t(q: Nat, b: Bool, t2: Word(q), e: {h.isz(1n+q, WCon{b, t2}) == True{} : Bool})
1989  -> {h.isz(q, Word.shl.put(q, b, t2)) == True{} : Bool}:
1990  match b:
1991    case True{}:
1992      Empty.absurd({h.isz(q, Word.shl.put(q, True{}, t2)) == True{} : Bool}, MBool.false_ne_true()(e))
1993    case False{}:
1994      h.isz_put(q, t2, e)
1995
1996def h.at1_put(p: Nat, t: Word(p), c: Bool, e: {h.at1(1n+p, WCon{c, t}) == True{} : Bool})
1997  -> {h.at1(p, Word.shl.put(p, c, t)) == True{} : Bool}:
1998  match p:
1999    case 0n:
2000      {==}
2001    case 1n+q:
2002      match t:
2003        case WCon{b, t2}:
2004          match c:
2005            case True{}:
2006              h.at1_put.t(q, b, t2, e)
2007            case False{}:
2008              h.at1_put(q, t2, b, e)
2009
2010def h.at1_shl(n: Nat, w: Word(n), e: {h.at1(n, w) == True{} : Bool})
2011  -> {h.at1(n, Word.shl(n, w)) == True{} : Bool}:
2012  match n:
2013    case 0n:
2014      {==}
2015    case 1n+p:
2016      match w:
2017        case WCon{b, t}:
2018          h.at1_put(p, t, b, e)
2019
2020def h.onebit_shl(m: U32, e: {h.onebit(m) == True{} : Bool}) -> {h.onebit((m << 1n : U32)) == True{} : Bool}:
2021  match m:
2022    case U32{w}:
2023      h.at1_shl(32n, w, e)
2024
2025# --- buckets ---------------------------------------------------------------------
2026
2027def h.egc(
2028  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, b: Bool, +val: V,
2029  rest: List<&2, M.Entry<K, V>>, +k: K
2030) -> Maybe<&2, V>:
2031  M.HMap.bool(Maybe<&2, V>, b, u => Some{val}, u => M.HMap.entries.get(~K, ~V, ~eq, rest, k))
2032
2033def h.epc(
2034  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, b: Bool, +key: K, +val: V,
2035  +rest: List<&2, M.Entry<K, V>>, +k: K, +v: V
2036) -> List<&2, M.Entry<K, V>>:
2037  M.HMap.bool(List<&2, M.Entry<K, V>>, b,
2038    u => M.Entry{key, v} <> rest,
2039    u => M.Entry{key, val} <> M.HMap.entries.put(~K, ~V, ~eq, rest, k, v))
2040
2041def h.edc(
2042  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, b: Bool, +key: K, +val: V,
2043  +rest: List<&2, M.Entry<K, V>>, +k: K
2044) -> List<&2, M.Entry<K, V>>:
2045  M.HMap.bool(List<&2, M.Entry<K, V>>, b,
2046    u => rest,
2047    u => M.Entry{key, val} <> M.HMap.entries.del(~K, ~V, ~eq, rest, k))
2048
2049def h.egc2(
2050  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, c: Bool, +val: V,
2051  +xs: List<&2, M.Entry<K, V>>, +ys: List<&2, M.Entry<K, V>>, +k: K,
2052  e: {M.HMap.entries.get(~K, ~V, ~eq, xs, k) == M.HMap.entries.get(~K, ~V, ~eq, ys, k) : Maybe<&2, V>}
2053) -> {h.egc(~K, ~V, ~eq, c, val, xs, k) == h.egc(~K, ~V, ~eq, c, val, ys, k) : Maybe<&2, V>}:
2054  match c:
2055    case True{}:
2056      {==}
2057    case False{}:
2058      e
2059
2060# eq(k, k2) is False when k2 != k.
2061def h.ne_f.c(
2062  ~K: Data, ~eq: K -> K -> Bool,
2063  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
2064  +k2: K, +k: K, ne: {k2 != k : K}, b: Bool, eb: {b == eq(k, k2) : Bool}
2065) -> {b == False{} : Bool}:
2066  match b:
2067    case True{}:
2068      Empty.absurd({True{} == False{} : Bool}, ne(Equal.sym(K, k, k2, sound(k, k2, h.sb(True{}, eq(k, k2), eb)))))
2069    case False{}:
2070      {==}
2071
2072def h.ne_f(
2073  ~K: Data, ~eq: K -> K -> Bool,
2074  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
2075  +k2: K, +k: K, ne: {k2 != k : K}
2076) -> {eq(k, k2) == False{} : Bool}:
2077  h.ne_f.c(~K, ~eq, ~sound, k2, k, ne, eq(k, k2), {==})
2078
2079# eq(k, key) is False when key is equal to k2 and eq(k, k2) is False.
2080def h.nk(
2081  ~K: Data, ~eq: K -> K -> Bool,
2082  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
2083  +k2: K, +key: K, +k: K, e: {eq(k2, key) == True{} : Bool}, ne: {eq(k, k2) == False{} : Bool}
2084) -> {eq(k, key) == False{} : Bool}:
2085  rw(K, z => {eq(k, z) == False{} : Bool}, key, k2, Equal.sym(K, k2, key, sound(k2, key, e)), ne)
2086
2087def h.eg_put_same.c(
2088  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +key: K, +val: V,
2089  +rest: List<&2, M.Entry<K, V>>, +k: K, +v: V, b: Bool, eb: {b == eq(k, key) : Bool},
2090  ih: {M.HMap.entries.get(~K, ~V, ~eq, M.HMap.entries.put(~K, ~V, ~eq, rest, k, v), k) == Some{v} : Maybe<&2, V>}
2091) -> {M.HMap.entries.get(~K, ~V, ~eq, h.epc(~K, ~V, ~eq, b, key, val, rest, k, v), k) == Some{v} : Maybe<&2, V>}:
2092  match b:
2093    case True{}:
2094      %eb : {h.egc(~K, ~V, ~eq, _, v, rest, k) == Some{v} : Maybe<&2, V>}
2095      {==}
2096    case False{}:
2097      %eb : {h.egc(~K, ~V, ~eq, _, val, M.HMap.entries.put(~K, ~V, ~eq, rest, k, v), k) == Some{v} : Maybe<&2, V>}
2098      ih
2099
2100def h.eg_put_same(
2101  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, ~refl: @x: K -> {eq(x, x) == True{} : Bool},
2102  xs: List<&2, M.Entry<K, V>>, +k: K, +v: V
2103) -> {M.HMap.entries.get(~K, ~V, ~eq, M.HMap.entries.put(~K, ~V, ~eq, xs, k, v), k) == Some{v} : Maybe<&2, V>}:
2104  match xs:
2105    case Nil{}:
2106      %h.sb(eq(k, k), True{}, refl(k)) : {h.egc(~K, ~V, ~eq, _, v, Nil{}, k) == Some{v} : Maybe<&2, V>}
2107      {==}
2108    case Con{M.Entry{+key, +val}, +rest}:
2109      h.eg_put_same.c(~K, ~V, ~eq, key, val, rest, k, v, eq(k, key), {==},
2110        h.eg_put_same(~K, ~V, ~eq, ~refl, rest, k, v))
2111
2112def h.eg_put_other.c(
2113  ~K: Data, ~V: Data, ~eq: K -> K -> Bool,
2114  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
2115  +key: K, +val: V, +rest: List<&2, M.Entry<K, V>>, +k2: K, +k: K, +v: V,
2116  +ne: {eq(k, k2) == False{} : Bool}, b: Bool, eb: {b == eq(k2, key) : Bool},
2117  ih: {M.HMap.entries.get(~K, ~V, ~eq, M.HMap.entries.put(~K, ~V, ~eq, rest, k2, v), k)
2118       == M.HMap.entries.get(~K, ~V, ~eq, rest, k) : Maybe<&2, V>}
2119) -> {M.HMap.entries.get(~K, ~V, ~eq, h.epc(~K, ~V, ~eq, b, key, val, rest, k2, v), k)
2120      == h.egc(~K, ~V, ~eq, eq(k, key), val, rest, k) : Maybe<&2, V>}:
2121  match b:
2122    case True{}:
2123      +nk = h.nk(~K, ~eq, ~sound, k2, key, k, h.sb(True{}, eq(k2, key), eb), ne)
2124      %h.sb(eq(k, key), False{}, nk)
2125        : {h.egc(~K, ~V, ~eq, _, v, rest, k) == h.egc(~K, ~V, ~eq, eq(k, key), val, rest, k) : Maybe<&2, V>}
2126      %h.sb(eq(k, key), False{}, nk)
2127        : {M.HMap.entries.get(~K, ~V, ~eq, rest, k) == h.egc(~K, ~V, ~eq, _, val, rest, k) : Maybe<&2, V>}
2128      {==}
2129    case False{}:
2130      h.egc2(~K, ~V, ~eq, eq(k, key), val, M.HMap.entries.put(~K, ~V, ~eq, rest, k2, v), rest, k, ih)
2131
2132def h.eg_put_other(
2133  ~K: Data, ~V: Data, ~eq: K -> K -> Bool,
2134  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
2135  xs: List<&2, M.Entry<K, V>>, +k2: K, +k: K, +v: V, +ne: {eq(k, k2) == False{} : Bool}
2136) -> {M.HMap.entries.get(~K, ~V, ~eq, M.HMap.entries.put(~K, ~V, ~eq, xs, k2, v), k)
2137      == M.HMap.entries.get(~K, ~V, ~eq, xs, k) : Maybe<&2, V>}:
2138  match xs:
2139    case Nil{}:
2140      %h.sb(eq(k, k2), False{}, ne) : {h.egc(~K, ~V, ~eq, _, v, Nil{}, k) == None{} : Maybe<&2, V>}
2141      {==}
2142    case Con{M.Entry{+key, +val}, +rest}:
2143      h.eg_put_other.c(~K, ~V, ~eq, ~sound, key, val, rest, k2, k, v, ne, eq(k2, key), {==},
2144        h.eg_put_other(~K, ~V, ~eq, ~sound, rest, k2, k, v, ne))
2145
2146# A bucket whose keys all hash to o holds no key hashing elsewhere.
2147def h.eg_none_hashed.c(
2148  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool,
2149  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
2150  +key: K, +val: V, +rest: List<&2, M.Entry<K, V>>, +o: U32, +k: K,
2151  hk: {U32.is_eq(o, hash(k)) == False{} : Bool}, hh: {U32.is_eq(o, hash(key)) == True{} : Bool},
2152  b: Bool, eb: {b == eq(k, key) : Bool},
2153  ih: {M.HMap.entries.get(~K, ~V, ~eq, rest, k) == None{} : Maybe<&2, V>}
2154) -> {h.egc(~K, ~V, ~eq, b, val, rest, k) == None{} : Maybe<&2, V>}:
2155  match b:
2156    case True{}:
2157      h.tf({h.egc(~K, ~V, ~eq, True{}, val, rest, k) == None{} : Maybe<&2, V>}, U32.is_eq(o, hash(k)),
2158        rw(K, z => {U32.is_eq(o, hash(z)) == True{} : Bool}, k, key,
2159          sound(k, key, h.sb(True{}, eq(k, key), eb)), hh),
2160        hk)
2161    case False{}:
2162      ih
2163
2164def h.eg_none_hashed(
2165  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool,
2166  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
2167  xs: List<&2, M.Entry<K, V>>, +o: U32, +k: K, +hk: {U32.is_eq(o, hash(k)) == False{} : Bool},
2168  hs: {Laws.hmap_hashed(~K, ~V, ~hash, xs, o) == True{} : Bool}
2169) -> {M.HMap.entries.get(~K, ~V, ~eq, xs, k) == None{} : Maybe<&2, V>}:
2170  match xs:
2171    case Nil{}:
2172      {==}
2173    case Con{M.Entry{+key, +val}, +rest}:
2174      +hs = hs
2175      h.eg_none_hashed.c(~K, ~V, ~hash, ~eq, ~sound, key, val, rest, o, k, hk,
2176        MBool.eq_true_of_and_left(U32.is_eq(o, hash(key)), Laws.hmap_hashed(~K, ~V, ~hash, rest, o), hs),
2177        eq(k, key), {==},
2178        h.eg_none_hashed(~K, ~V, ~hash, ~eq, ~sound, rest, o, k, hk,
2179          MBool.eq_true_of_and_right(U32.is_eq(o, hash(key)), Laws.hmap_hashed(~K, ~V, ~hash, rest, o), hs)))
2180
2181def h.len(-K: Data, -V: Data, xs: List<&2, M.Entry<K, V>>) -> Nat:
2182  List.length(&2, M.Entry<K, V>, xs)
2183
2184def h.elen_put_new.c(
2185  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +key: K, +val: V,
2186  +rest: List<&2, M.Entry<K, V>>, +k: K, +v: V, b: Bool,
2187  miss: {h.egc(~K, ~V, ~eq, b, val, rest, k) == None{} : Maybe<&2, V>},
2188  ih: {M.HMap.entries.get(~K, ~V, ~eq, rest, k) == None{} : Maybe<&2, V>}
2189    -> {h.len(K, V, M.HMap.entries.put(~K, ~V, ~eq, rest, k, v)) == 1n+h.len(K, V, rest) : Nat}
2190) -> {h.len(K, V, h.epc(~K, ~V, ~eq, b, key, val, rest, k, v)) == 1n+1n+h.len(K, V, rest) : Nat}:
2191  match b:
2192    case True{}:
2193      h.some_none({h.len(K, V, M.Entry{key, v} <> rest) == 1n+1n+h.len(K, V, rest) : Nat}, V, val, miss)
2194    case False{}:
2195      Equal.cong(Nat, Nat, x => 1n+x, h.len(K, V, M.HMap.entries.put(~K, ~V, ~eq, rest, k, v)),
2196        1n+h.len(K, V, rest), ih(miss))
2197
2198def h.elen_put_new(
2199  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, xs: List<&2, M.Entry<K, V>>, +k: K, +v: V,
2200  miss: {M.HMap.entries.get(~K, ~V, ~eq, xs, k) == None{} : Maybe<&2, V>}
2201) -> {h.len(K, V, M.HMap.entries.put(~K, ~V, ~eq, xs, k, v)) == 1n+h.len(K, V, xs) : Nat}:
2202  match xs:
2203    case Nil{}:
2204      {==}
2205    case Con{M.Entry{+key, +val}, +rest}:
2206      h.elen_put_new.c(~K, ~V, ~eq, key, val, rest, k, v, eq(k, key), miss,
2207        e => h.elen_put_new(~K, ~V, ~eq, rest, k, v, e))
2208
2209def h.elen_put_hit.c(
2210  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +key: K, +val: V,
2211  +rest: List<&2, M.Entry<K, V>>, +k: K, +v: V, -w: V, b: Bool,
2212  hit: {h.egc(~K, ~V, ~eq, b, val, rest, k) == Some{w} : Maybe<&2, V>},
2213  ih: {M.HMap.entries.get(~K, ~V, ~eq, rest, k) == Some{w} : Maybe<&2, V>}
2214    -> {h.len(K, V, M.HMap.entries.put(~K, ~V, ~eq, rest, k, v)) == h.len(K, V, rest) : Nat}
2215) -> {h.len(K, V, h.epc(~K, ~V, ~eq, b, key, val, rest, k, v)) == 1n+h.len(K, V, rest) : Nat}:
2216  match b:
2217    case True{}:
2218      {==}
2219    case False{}:
2220      Equal.cong(Nat, Nat, x => 1n+x, h.len(K, V, M.HMap.entries.put(~K, ~V, ~eq, rest, k, v)),
2221        h.len(K, V, rest), ih(hit))
2222
2223def h.elen_put_hit(
2224  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, xs: List<&2, M.Entry<K, V>>, +k: K, +v: V, -w: V,
2225  hit: {M.HMap.entries.get(~K, ~V, ~eq, xs, k) == Some{w} : Maybe<&2, V>}
2226) -> {h.len(K, V, M.HMap.entries.put(~K, ~V, ~eq, xs, k, v)) == h.len(K, V, xs) : Nat}:
2227  match xs:
2228    case Nil{}:
2229      h.none_some({h.len(K, V, M.HMap.entries.put(~K, ~V, ~eq, Nil{}, k, v)) == 0n : Nat}, V, w, hit)
2230    case Con{M.Entry{+key, +val}, +rest}:
2231      h.elen_put_hit.c(~K, ~V, ~eq, key, val, rest, k, v, w, eq(k, key), hit,
2232        e => h.elen_put_hit(~K, ~V, ~eq, rest, k, v, w, e))
2233
2234def h.elen_del_hit.c(
2235  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +key: K, +val: V,
2236  +rest: List<&2, M.Entry<K, V>>, +k: K, -w: V, b: Bool,
2237  hit: {h.egc(~K, ~V, ~eq, b, val, rest, k) == Some{w} : Maybe<&2, V>},
2238  ih: {M.HMap.entries.get(~K, ~V, ~eq, rest, k) == Some{w} : Maybe<&2, V>}
2239    -> {1n+h.len(K, V, M.HMap.entries.del(~K, ~V, ~eq, rest, k)) == h.len(K, V, rest) : Nat}
2240) -> {1n+h.len(K, V, h.edc(~K, ~V, ~eq, b, key, val, rest, k)) == 1n+h.len(K, V, rest) : Nat}:
2241  match b:
2242    case True{}:
2243      {==}
2244    case False{}:
2245      Equal.cong(Nat, Nat, x => 1n+x, 1n+h.len(K, V, M.HMap.entries.del(~K, ~V, ~eq, rest, k)),
2246        h.len(K, V, rest), ih(hit))
2247
2248def h.elen_del_hit(
2249  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, xs: List<&2, M.Entry<K, V>>, +k: K, -w: V,
2250  hit: {M.HMap.entries.get(~K, ~V, ~eq, xs, k) == Some{w} : Maybe<&2, V>}
2251) -> {1n+h.len(K, V, M.HMap.entries.del(~K, ~V, ~eq, xs, k)) == h.len(K, V, xs) : Nat}:
2252  match xs:
2253    case Nil{}:
2254      h.none_some({1n == 0n : Nat}, V, w, hit)
2255    case Con{M.Entry{+key, +val}, +rest}:
2256      h.elen_del_hit.c(~K, ~V, ~eq, key, val, rest, k, w, eq(k, key), hit,
2257        e => h.elen_del_hit(~K, ~V, ~eq, rest, k, w, e))
2258
2259def h.edel_miss.c(
2260  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +key: K, +val: V,
2261  +rest: List<&2, M.Entry<K, V>>, +k: K, b: Bool,
2262  miss: {h.egc(~K, ~V, ~eq, b, val, rest, k) == None{} : Maybe<&2, V>},
2263  ih: {M.HMap.entries.get(~K, ~V, ~eq, rest, k) == None{} : Maybe<&2, V>}
2264    -> {M.HMap.entries.del(~K, ~V, ~eq, rest, k) == rest : List<&2, M.Entry<K, V>>}
2265) -> {h.edc(~K, ~V, ~eq, b, key, val, rest, k) == M.Entry{key, val} <> rest : List<&2, M.Entry<K, V>>}:
2266  match b:
2267    case True{}:
2268      h.some_none({rest == M.Entry{key, val} <> rest : List<&2, M.Entry<K, V>>}, V, val, miss)
2269    case False{}:
2270      Equal.cong(List<&2, M.Entry<K, V>>, List<&2, M.Entry<K, V>>, t => M.Entry{key, val} <> t,
2271        M.HMap.entries.del(~K, ~V, ~eq, rest, k), rest, ih(miss))
2272
2273def h.edel_miss(
2274  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, xs: List<&2, M.Entry<K, V>>, +k: K,
2275  miss: {M.HMap.entries.get(~K, ~V, ~eq, xs, k) == None{} : Maybe<&2, V>}
2276) -> {M.HMap.entries.del(~K, ~V, ~eq, xs, k) == xs : List<&2, M.Entry<K, V>>}:
2277  match xs:
2278    case Nil{}:
2279      {==}
2280    case Con{M.Entry{+key, +val}, +rest}:
2281      h.edel_miss.c(~K, ~V, ~eq, key, val, rest, k, eq(k, key), miss,
2282        e => h.edel_miss(~K, ~V, ~eq, rest, k, e))
2283
2284def h.absent_none(
2285  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, xs: List<&2, M.Entry<K, V>>, +k: K,
2286  ab: {Laws.hmap_absent(~K, ~V, ~eq, xs, k) == True{} : Bool}
2287) -> {M.HMap.entries.get(~K, ~V, ~eq, xs, k) == None{} : Maybe<&2, V>}:
2288  match xs:
2289    case Nil{}:
2290      {==}
2291    case Con{M.Entry{+key, +val}, +rest}:
2292      +ab = ab
2293      %h.sb(eq(k, key), False{},
2294        MBool.eq_false_of_not_eq_true(eq(k, key), MBool.eq_true_of_and_left(Bool.not(eq(k, key)), Laws.hmap_absent(~K, ~V, ~eq, rest, k), ab)))
2295        : {h.egc(~K, ~V, ~eq, _, val, rest, k) == None{} : Maybe<&2, V>}
2296      h.absent_none(~K, ~V, ~eq, rest, k,
2297        MBool.eq_true_of_and_right(Bool.not(eq(k, key)), Laws.hmap_absent(~K, ~V, ~eq, rest, k), ab))
2298
2299def h.eg_del_same.c(
2300  ~K: Data, ~V: Data, ~eq: K -> K -> Bool,
2301  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
2302  +key: K, +val: V, +rest: List<&2, M.Entry<K, V>>, +k: K, b: Bool, eb: {b == eq(k, key) : Bool},
2303  ab: {Laws.hmap_absent(~K, ~V, ~eq, rest, key) == True{} : Bool},
2304  ih: {M.HMap.entries.get(~K, ~V, ~eq, M.HMap.entries.del(~K, ~V, ~eq, rest, k), k) == None{} : Maybe<&2, V>}
2305) -> {M.HMap.entries.get(~K, ~V, ~eq, h.edc(~K, ~V, ~eq, b, key, val, rest, k), k) == None{} : Maybe<&2, V>}:
2306  match b:
2307    case True{}:
2308      h.absent_none(~K, ~V, ~eq, rest, k,
2309        rw(K, z => {Laws.hmap_absent(~K, ~V, ~eq, rest, z) == True{} : Bool}, k, key,
2310          sound(k, key, h.sb(True{}, eq(k, key), eb)), ab))
2311    case False{}:
2312      %eb : {h.egc(~K, ~V, ~eq, _, val, M.HMap.entries.del(~K, ~V, ~eq, rest, k), k) == None{} : Maybe<&2, V>}
2313      ih
2314
2315def h.eg_del_same(
2316  ~K: Data, ~V: Data, ~eq: K -> K -> Bool,
2317  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
2318  xs: List<&2, M.Entry<K, V>>, +k: K,
2319  ds: {Laws.hmap_distinct(~K, ~V, ~eq, xs) == True{} : Bool}
2320) -> {M.HMap.entries.get(~K, ~V, ~eq, M.HMap.entries.del(~K, ~V, ~eq, xs, k), k) == None{} : Maybe<&2, V>}:
2321  match xs:
2322    case Nil{}:
2323      {==}
2324    case Con{M.Entry{+key, +val}, +rest}:
2325      +ds = ds
2326      h.eg_del_same.c(~K, ~V, ~eq, ~sound, key, val, rest, k, eq(k, key), {==},
2327        MBool.eq_true_of_and_left(Laws.hmap_absent(~K, ~V, ~eq, rest, key), Laws.hmap_distinct(~K, ~V, ~eq, rest), ds),
2328        h.eg_del_same(~K, ~V, ~eq, ~sound, rest, k,
2329          MBool.eq_true_of_and_right(Laws.hmap_absent(~K, ~V, ~eq, rest, key), Laws.hmap_distinct(~K, ~V, ~eq, rest), ds)))
2330
2331def h.eg_del_other.c(
2332  ~K: Data, ~V: Data, ~eq: K -> K -> Bool,
2333  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
2334  +key: K, +val: V, +rest: List<&2, M.Entry<K, V>>, +k2: K, +k: K,
2335  +ne: {eq(k, k2) == False{} : Bool}, b: Bool, eb: {b == eq(k2, key) : Bool},
2336  ih: {M.HMap.entries.get(~K, ~V, ~eq, M.HMap.entries.del(~K, ~V, ~eq, rest, k2), k)
2337       == M.HMap.entries.get(~K, ~V, ~eq, rest, k) : Maybe<&2, V>}
2338) -> {M.HMap.entries.get(~K, ~V, ~eq, h.edc(~K, ~V, ~eq, b, key, val, rest, k2), k)
2339      == h.egc(~K, ~V, ~eq, eq(k, key), val, rest, k) : Maybe<&2, V>}:
2340  match b:
2341    case True{}:
2342      %h.sb(eq(k, key), False{}, h.nk(~K, ~eq, ~sound, k2, key, k, h.sb(True{}, eq(k2, key), eb), ne))
2343        : {M.HMap.entries.get(~K, ~V, ~eq, rest, k) == h.egc(~K, ~V, ~eq, _, val, rest, k) : Maybe<&2, V>}
2344      {==}
2345    case False{}:
2346      h.egc2(~K, ~V, ~eq, eq(k, key), val, M.HMap.entries.del(~K, ~V, ~eq, rest, k2), rest, k, ih)
2347
2348def h.eg_del_other(
2349  ~K: Data, ~V: Data, ~eq: K -> K -> Bool,
2350  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
2351  xs: List<&2, M.Entry<K, V>>, +k2: K, +k: K, +ne: {eq(k, k2) == False{} : Bool}
2352) -> {M.HMap.entries.get(~K, ~V, ~eq, M.HMap.entries.del(~K, ~V, ~eq, xs, k2), k)
2353      == M.HMap.entries.get(~K, ~V, ~eq, xs, k) : Maybe<&2, V>}:
2354  match xs:
2355    case Nil{}:
2356      {==}
2357    case Con{M.Entry{+key, +val}, +rest}:
2358      h.eg_del_other.c(~K, ~V, ~eq, ~sound, key, val, rest, k2, k, ne, eq(k2, key), {==},
2359        h.eg_del_other(~K, ~V, ~eq, ~sound, rest, k2, k, ne))
2360
2361# eq is symmetric on False, given refl and sound.
2362def h.eq_sym_f.c(
2363  ~K: Data, ~eq: K -> K -> Bool, ~refl: @x: K -> {eq(x, x) == True{} : Bool},
2364  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
2365  +k: K, +key: K, e: {eq(k, key) == False{} : Bool}, b: Bool, eb: {b == eq(key, k) : Bool}
2366) -> {b == False{} : Bool}:
2367  match b:
2368    case True{}:
2369      h.tf({True{} == False{} : Bool}, eq(k, k), refl(k),
2370        rw(K, z => {eq(k, z) == False{} : Bool}, k, key,
2371          Equal.sym(K, key, k, sound(key, k, h.sb(True{}, eq(key, k), eb))), e))
2372    case False{}:
2373      {==}
2374
2375def h.eq_sym_f(
2376  ~K: Data, ~eq: K -> K -> Bool, ~refl: @x: K -> {eq(x, x) == True{} : Bool},
2377  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
2378  +k: K, +key: K, e: {eq(k, key) == False{} : Bool}
2379) -> {eq(key, k) == False{} : Bool}:
2380  h.eq_sym_f.c(~K, ~eq, ~refl, ~sound, k, key, e, eq(key, k), {==})
2381
2382def h.absent_put.c(
2383  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +key2: K, +val: V,
2384  +rest: List<&2, M.Entry<K, V>>, +key: K, +k: K, +v: V, b: Bool,
2385  +ab: {Laws.hmap_absent(~K, ~V, ~eq, M.Entry{key2, val} <> rest, key) == True{} : Bool},
2386  ih: {Laws.hmap_absent(~K, ~V, ~eq, M.HMap.entries.put(~K, ~V, ~eq, rest, k, v), key) == True{} : Bool}
2387) -> {Laws.hmap_absent(~K, ~V, ~eq, h.epc(~K, ~V, ~eq, b, key2, val, rest, k, v), key) == True{} : Bool}:
2388  match b:
2389    case True{}:
2390      ab
2391    case False{}:
2392      MBool.and_eq_true(Bool.not(eq(key, key2)), Laws.hmap_absent(~K, ~V, ~eq, M.HMap.entries.put(~K, ~V, ~eq, rest, k, v), key), MBool.eq_true_of_and_left(Bool.not(eq(key, key2)), Laws.hmap_absent(~K, ~V, ~eq, rest, key), ab), ih)
2393
2394def h.absent_put(
2395  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, ~refl: @x: K -> {eq(x, x) == True{} : Bool},
2396  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
2397  xs: List<&2, M.Entry<K, V>>, +key: K, +k: K, +v: V,
2398  ab: {Laws.hmap_absent(~K, ~V, ~eq, xs, key) == True{} : Bool},
2399  +nk: {eq(k, key) == False{} : Bool}
2400) -> {Laws.hmap_absent(~K, ~V, ~eq, M.HMap.entries.put(~K, ~V, ~eq, xs, k, v), key) == True{} : Bool}:
2401  match xs:
2402    case Nil{}:
2403      %h.sb(eq(key, k), False{}, h.eq_sym_f(~K, ~eq, ~refl, ~sound, k, key, nk))
2404        : {Bool.and(Bool.not(_), True{}) == True{} : Bool}
2405      {==}
2406    case Con{M.Entry{+key2, +val}, +rest}:
2407      +ab = ab
2408      h.absent_put.c(~K, ~V, ~eq, key2, val, rest, key, k, v, eq(k, key2), ab,
2409        h.absent_put(~K, ~V, ~eq, ~refl, ~sound, rest, key, k, v,
2410          MBool.eq_true_of_and_right(Bool.not(eq(key, key2)), Laws.hmap_absent(~K, ~V, ~eq, rest, key), ab), nk))
2411
2412def h.distinct_put.c(
2413  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, ~refl: @x: K -> {eq(x, x) == True{} : Bool},
2414  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
2415  +key: K, +val: V, +rest: List<&2, M.Entry<K, V>>, +k: K, +v: V, b: Bool, eb: {b == eq(k, key) : Bool},
2416  +ds: {Laws.hmap_distinct(~K, ~V, ~eq, M.Entry{key, val} <> rest) == True{} : Bool},
2417  ih: {Laws.hmap_distinct(~K, ~V, ~eq, M.HMap.entries.put(~K, ~V, ~eq, rest, k, v)) == True{} : Bool}
2418) -> {Laws.hmap_distinct(~K, ~V, ~eq, h.epc(~K, ~V, ~eq, b, key, val, rest, k, v)) == True{} : Bool}:
2419  match b:
2420    case True{}:
2421      ds
2422    case False{}:
2423      MBool.and_eq_true(Laws.hmap_absent(~K, ~V, ~eq, M.HMap.entries.put(~K, ~V, ~eq, rest, k, v), key), Laws.hmap_distinct(~K, ~V, ~eq, M.HMap.entries.put(~K, ~V, ~eq, rest, k, v)), h.absent_put(~K, ~V, ~eq, ~refl, ~sound, rest, key, k, v,
2424          MBool.eq_true_of_and_left(Laws.hmap_absent(~K, ~V, ~eq, rest, key), Laws.hmap_distinct(~K, ~V, ~eq, rest), ds),
2425          h.sb(False{}, eq(k, key), eb)), ih)
2426
2427def h.distinct_put(
2428  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, ~refl: @x: K -> {eq(x, x) == True{} : Bool},
2429  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
2430  xs: List<&2, M.Entry<K, V>>, +k: K, +v: V,
2431  ds: {Laws.hmap_distinct(~K, ~V, ~eq, xs) == True{} : Bool}
2432) -> {Laws.hmap_distinct(~K, ~V, ~eq, M.HMap.entries.put(~K, ~V, ~eq, xs, k, v)) == True{} : Bool}:
2433  match xs:
2434    case Nil{}:
2435      {==}
2436    case Con{M.Entry{+key, +val}, +rest}:
2437      +ds = ds
2438      h.distinct_put.c(~K, ~V, ~eq, ~refl, ~sound, key, val, rest, k, v, eq(k, key), {==}, ds,
2439        h.distinct_put(~K, ~V, ~eq, ~refl, ~sound, rest, k, v,
2440          MBool.eq_true_of_and_right(Laws.hmap_absent(~K, ~V, ~eq, rest, key), Laws.hmap_distinct(~K, ~V, ~eq, rest), ds)))
2441
2442def h.hashed_put.c(
2443  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool, +key: K, +val: V,
2444  +rest: List<&2, M.Entry<K, V>>, +o: U32, +k: K, +v: V, b: Bool,
2445  +hs: {Laws.hmap_hashed(~K, ~V, ~hash, M.Entry{key, val} <> rest, o) == True{} : Bool},
2446  ih: {Laws.hmap_hashed(~K, ~V, ~hash, M.HMap.entries.put(~K, ~V, ~eq, rest, k, v), o) == True{} : Bool}
2447) -> {Laws.hmap_hashed(~K, ~V, ~hash, h.epc(~K, ~V, ~eq, b, key, val, rest, k, v), o) == True{} : Bool}:
2448  match b:
2449    case True{}:
2450      hs
2451    case False{}:
2452      MBool.and_eq_true(U32.is_eq(o, hash(key)), Laws.hmap_hashed(~K, ~V, ~hash, M.HMap.entries.put(~K, ~V, ~eq, rest, k, v), o), MBool.eq_true_of_and_left(U32.is_eq(o, hash(key)), Laws.hmap_hashed(~K, ~V, ~hash, rest, o), hs), ih)
2453
2454def h.hashed_put(
2455  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool,
2456  xs: List<&2, M.Entry<K, V>>, +o: U32, +k: K, +v: V,
2457  +hk: {U32.is_eq(o, hash(k)) == True{} : Bool},
2458  hs: {Laws.hmap_hashed(~K, ~V, ~hash, xs, o) == True{} : Bool}
2459) -> {Laws.hmap_hashed(~K, ~V, ~hash, M.HMap.entries.put(~K, ~V, ~eq, xs, k, v), o) == True{} : Bool}:
2460  match xs:
2461    case Nil{}:
2462      %h.sb(U32.is_eq(o, hash(k)), True{}, hk) : {Bool.and(_, True{}) == True{} : Bool}
2463      {==}
2464    case Con{M.Entry{+key, +val}, +rest}:
2465      +hs = hs
2466      h.hashed_put.c(~K, ~V, ~hash, ~eq, key, val, rest, o, k, v, eq(k, key), hs,
2467        h.hashed_put(~K, ~V, ~hash, ~eq, rest, o, k, v, hk,
2468          MBool.eq_true_of_and_right(U32.is_eq(o, hash(key)), Laws.hmap_hashed(~K, ~V, ~hash, rest, o), hs)))
2469
2470def h.absent_del.c(
2471  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +key2: K, +val: V,
2472  +rest: List<&2, M.Entry<K, V>>, +key: K, +k: K, b: Bool,
2473  +ab: {Laws.hmap_absent(~K, ~V, ~eq, M.Entry{key2, val} <> rest, key) == True{} : Bool},
2474  ih: {Laws.hmap_absent(~K, ~V, ~eq, M.HMap.entries.del(~K, ~V, ~eq, rest, k), key) == True{} : Bool}
2475) -> {Laws.hmap_absent(~K, ~V, ~eq, h.edc(~K, ~V, ~eq, b, key2, val, rest, k), key) == True{} : Bool}:
2476  match b:
2477    case True{}:
2478      MBool.eq_true_of_and_right(Bool.not(eq(key, key2)), Laws.hmap_absent(~K, ~V, ~eq, rest, key), ab)
2479    case False{}:
2480      MBool.and_eq_true(Bool.not(eq(key, key2)), Laws.hmap_absent(~K, ~V, ~eq, M.HMap.entries.del(~K, ~V, ~eq, rest, k), key), MBool.eq_true_of_and_left(Bool.not(eq(key, key2)), Laws.hmap_absent(~K, ~V, ~eq, rest, key), ab), ih)
2481
2482def h.absent_del(
2483  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, xs: List<&2, M.Entry<K, V>>, +key: K, +k: K,
2484  ab: {Laws.hmap_absent(~K, ~V, ~eq, xs, key) == True{} : Bool}
2485) -> {Laws.hmap_absent(~K, ~V, ~eq, M.HMap.entries.del(~K, ~V, ~eq, xs, k), key) == True{} : Bool}:
2486  match xs:
2487    case Nil{}:
2488      {==}
2489    case Con{M.Entry{+key2, +val}, +rest}:
2490      +ab = ab
2491      h.absent_del.c(~K, ~V, ~eq, key2, val, rest, key, k, eq(k, key2), ab,
2492        h.absent_del(~K, ~V, ~eq, rest, key, k,
2493          MBool.eq_true_of_and_right(Bool.not(eq(key, key2)), Laws.hmap_absent(~K, ~V, ~eq, rest, key), ab)))
2494
2495def h.distinct_del.c(
2496  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +key: K, +val: V,
2497  +rest: List<&2, M.Entry<K, V>>, +k: K, b: Bool,
2498  +ds: {Laws.hmap_distinct(~K, ~V, ~eq, M.Entry{key, val} <> rest) == True{} : Bool},
2499  ih: {Laws.hmap_distinct(~K, ~V, ~eq, M.HMap.entries.del(~K, ~V, ~eq, rest, k)) == True{} : Bool}
2500) -> {Laws.hmap_distinct(~K, ~V, ~eq, h.edc(~K, ~V, ~eq, b, key, val, rest, k)) == True{} : Bool}:
2501  match b:
2502    case True{}:
2503      MBool.eq_true_of_and_right(Laws.hmap_absent(~K, ~V, ~eq, rest, key), Laws.hmap_distinct(~K, ~V, ~eq, rest), ds)
2504    case False{}:
2505      MBool.and_eq_true(Laws.hmap_absent(~K, ~V, ~eq, M.HMap.entries.del(~K, ~V, ~eq, rest, k), key), Laws.hmap_distinct(~K, ~V, ~eq, M.HMap.entries.del(~K, ~V, ~eq, rest, k)), h.absent_del(~K, ~V, ~eq, rest, key, k,
2506          MBool.eq_true_of_and_left(Laws.hmap_absent(~K, ~V, ~eq, rest, key), Laws.hmap_distinct(~K, ~V, ~eq, rest), ds)), ih)
2507
2508def h.distinct_del(
2509  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, xs: List<&2, M.Entry<K, V>>, +k: K,
2510  ds: {Laws.hmap_distinct(~K, ~V, ~eq, xs) == True{} : Bool}
2511) -> {Laws.hmap_distinct(~K, ~V, ~eq, M.HMap.entries.del(~K, ~V, ~eq, xs, k)) == True{} : Bool}:
2512  match xs:
2513    case Nil{}:
2514      {==}
2515    case Con{M.Entry{+key, +val}, +rest}:
2516      +ds = ds
2517      h.distinct_del.c(~K, ~V, ~eq, key, val, rest, k, eq(k, key), ds,
2518        h.distinct_del(~K, ~V, ~eq, rest, k,
2519          MBool.eq_true_of_and_right(Laws.hmap_absent(~K, ~V, ~eq, rest, key), Laws.hmap_distinct(~K, ~V, ~eq, rest), ds)))
2520
2521def h.hashed_del.c(
2522  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool, +key: K, +val: V,
2523  +rest: List<&2, M.Entry<K, V>>, +o: U32, +k: K, b: Bool,
2524  +hs: {Laws.hmap_hashed(~K, ~V, ~hash, M.Entry{key, val} <> rest, o) == True{} : Bool},
2525  ih: {Laws.hmap_hashed(~K, ~V, ~hash, M.HMap.entries.del(~K, ~V, ~eq, rest, k), o) == True{} : Bool}
2526) -> {Laws.hmap_hashed(~K, ~V, ~hash, h.edc(~K, ~V, ~eq, b, key, val, rest, k), o) == True{} : Bool}:
2527  match b:
2528    case True{}:
2529      MBool.eq_true_of_and_right(U32.is_eq(o, hash(key)), Laws.hmap_hashed(~K, ~V, ~hash, rest, o), hs)
2530    case False{}:
2531      MBool.and_eq_true(U32.is_eq(o, hash(key)), Laws.hmap_hashed(~K, ~V, ~hash, M.HMap.entries.del(~K, ~V, ~eq, rest, k), o), MBool.eq_true_of_and_left(U32.is_eq(o, hash(key)), Laws.hmap_hashed(~K, ~V, ~hash, rest, o), hs), ih)
2532
2533def h.hashed_del(
2534  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool,
2535  xs: List<&2, M.Entry<K, V>>, +o: U32, +k: K,
2536  hs: {Laws.hmap_hashed(~K, ~V, ~hash, xs, o) == True{} : Bool}
2537) -> {Laws.hmap_hashed(~K, ~V, ~hash, M.HMap.entries.del(~K, ~V, ~eq, xs, k), o) == True{} : Bool}:
2538  match xs:
2539    case Nil{}:
2540      {==}
2541    case Con{M.Entry{+key, +val}, +rest}:
2542      +hs = hs
2543      h.hashed_del.c(~K, ~V, ~hash, ~eq, key, val, rest, o, k, eq(k, key), hs,
2544        h.hashed_del(~K, ~V, ~hash, ~eq, rest, o, k,
2545          MBool.eq_true_of_and_right(U32.is_eq(o, hash(key)), Laws.hmap_hashed(~K, ~V, ~hash, rest, o), hs)))
2546
2547# --- tries -----------------------------------------------------------------------
2548
2549def h.G(~K: Data, ~V: Data, ~eq: K -> K -> Bool, +n: Nat, +mask: U32, m: M.HMap<K, V>, +hk: U32, +k: K) -> Maybe<&2, V>:
2550  M.HMap.get.go(~K, ~V, ~eq, n, mask, m, hk, k)
2551
2552def h.P(~K: Data, ~V: Data, ~eq: K -> K -> Bool, +n: Nat, +mask: U32, m: M.HMap<K, V>, +hk: U32, +k: K, +v: V) -> M.HMap<K, V>:
2553  M.HMap.put.go(~K, ~V, ~eq, n, mask, m, hk, k, v)
2554
2555def h.D(~K: Data, ~V: Data, ~eq: K -> K -> Bool, +n: Nat, +mask: U32, m: M.HMap<K, V>, +hk: U32, +k: K) -> M.HMap<K, V>:
2556  M.HMap.del.go(~K, ~V, ~eq, n, mask, m, hk, k)
2557
2558def h.S(
2559  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +n: Nat, +mask: U32, +o: U32,
2560  +es: List<&2, M.Entry<K, V>>, +hk: U32, +k: K, +v: V
2561) -> M.HMap<K, V>:
2562  M.HMap.split(~K, ~V, ~eq, n, mask, o, es, hk, k, v)
2563
2564def h.EG(~K: Data, ~V: Data, ~eq: K -> K -> Bool, xs: List<&2, M.Entry<K, V>>, +k: K) -> Maybe<&2, V>:
2565  M.HMap.entries.get(~K, ~V, ~eq, xs, k)
2566
2567def h.WF(~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool, +n: Nat, m: M.HMap<K, V>) -> Bool:
2568  Laws.hmap_wf.go(~K, ~V, ~hash, ~eq, n, m)
2569
2570def h.Sz(-K: Data, -V: Data, m: M.HMap<K, V>) -> Nat:
2571  M.HMap.size(K, V, m)
2572
2573# The branches of put.go, split, and del.go, with their test as a parameter.
2574def h.pl(
2575  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, b: Bool, +p: Nat, +mask: U32, +o: U32,
2576  +es: List<&2, M.Entry<K, V>>, +hk: U32, +k: K, +v: V
2577) -> M.HMap<K, V>:
2578  M.HMap.bool(M.HMap<K, V>, b,
2579    u => M.HLeaf{o, M.HMap.entries.put(~K, ~V, ~eq, es, k, v)},
2580    u => M.HMap.split(~K, ~V, ~eq, 1n+p, mask, o, es, hk, k, v))
2581
2582def h.pb(
2583  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, b: Bool, +p: Nat, +mask: U32,
2584  +lo: M.HMap<K, V>, +hi: M.HMap<K, V>, +hk: U32, +k: K, +v: V
2585) -> M.HMap<K, V>:
2586  M.HMap.bool(M.HMap<K, V>, b,
2587    u => M.HBranch{M.HMap.put.go(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k, v), hi},
2588    u => M.HBranch{lo, M.HMap.put.go(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k, v)})
2589
2590def h.sp(
2591  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, b1: Bool, +b2: Bool, +p: Nat, +mask: U32, +o: U32,
2592  +es: List<&2, M.Entry<K, V>>, +hk: U32, +k: K, +v: V
2593) -> M.HMap<K, V>:
2594  M.HMap.bool(M.HMap<K, V>, b1,
2595    u => M.HMap.bool(M.HMap<K, V>, b2,
2596      x => M.HBranch{M.HMap.split(~K, ~V, ~eq, p, (mask << 1n : U32), o, es, hk, k, v), M.HNil{}},
2597      x => M.HBranch{M.HNil{}, M.HMap.split(~K, ~V, ~eq, p, (mask << 1n : U32), o, es, hk, k, v)}),
2598    u => M.HMap.split.side(K, V, b2, M.HLeaf{o, es}, M.HLeaf{hk, [M.Entry{k, v}]}))
2599
2600def h.dl(
2601  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, b: Bool, +o: U32, +es: List<&2, M.Entry<K, V>>, +k: K
2602) -> M.HMap<K, V>:
2603  M.HMap.bool(M.HMap<K, V>, b,
2604    u => M.HMap.leaf(K, V, o, M.HMap.entries.del(~K, ~V, ~eq, es, k)),
2605    u => M.HLeaf{o, es})
2606
2607def h.db(
2608  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, b: Bool, +p: Nat, +mask: U32,
2609  +lo: M.HMap<K, V>, +hi: M.HMap<K, V>, +hk: U32, +k: K
2610) -> M.HMap<K, V>:
2611  M.HMap.bool(M.HMap<K, V>, b,
2612    u => M.HMap.join(K, V, M.HMap.del.go(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k), hi),
2613    u => M.HMap.join(K, V, lo, M.HMap.del.go(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)))
2614
2615# get on a bucket, as get.go sees it above the last level.
2616def h.R(
2617  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool, +o: U32,
2618  +es: List<&2, M.Entry<K, V>>, +k: K
2619) -> Maybe<&2, V>:
2620  M.HMap.bool(Maybe<&2, V>, U32.is_eq(o, hash(k)), u => M.HMap.entries.get(~K, ~V, ~eq, es, k), u => None{})
2621
2622def h.bool_none(-V: Data, b: Bool, -x: Maybe<&2, V>, e: {x == None{} : Maybe<&2, V>})
2623  -> {M.HMap.bool(Maybe<&2, V>, b, u => x, u => None{}) == None{} : Maybe<&2, V>}:
2624  match b:
2625    case True{}:
2626      e
2627    case False{}:
2628      {==}
2629
2630def h.bnn(-V: Data, b: Bool, -x: Maybe<&2, V>, +e: {x == None{} : Maybe<&2, V>})
2631  -> {None{} == M.HMap.bool(Maybe<&2, V>, b, u => x, u => x) : Maybe<&2, V>}:
2632  match b:
2633    case True{}:
2634      Equal.sym(Maybe<&2, V>, x, None{}, e)
2635    case False{}:
2636      Equal.sym(Maybe<&2, V>, x, None{}, e)
2637
2638def h.bool_l(-A: Type, b: Bool, -x1: A, -x2: A, -y: A, e: {x1 == x2 : A})
2639  -> {M.HMap.bool(A, b, u => x1, u => y) == M.HMap.bool(A, b, u => x2, u => y) : A}:
2640  match b:
2641    case True{}:
2642      e
2643    case False{}:
2644      {==}
2645
2646def h.bool_r(-A: Type, b: Bool, -x: A, -y1: A, -y2: A, e: {y1 == y2 : A})
2647  -> {M.HMap.bool(A, b, u => x, u => y1) == M.HMap.bool(A, b, u => x, u => y2) : A}:
2648  match b:
2649    case True{}:
2650      {==}
2651    case False{}:
2652      e
2653
2654def h.bsel(
2655  -A: Type, b: Bool, -x: A, -y: A, -z: A,
2656  ht: {b == True{} : Bool} -> {x == z : A}, hf: {b == False{} : Bool} -> {y == z : A}
2657) -> {M.HMap.bool(A, b, u => x, u => y) == z : A}:
2658  match b:
2659    case True{}:
2660      ht({==})
2661    case False{}:
2662      hf({==})
2663
2664def h.cnc(c: Bool, e: {c == Bool.not(c) : Bool}) -> Empty:
2665  match c:
2666    case True{}:
2667      MBool.false_ne_true()(Equal.sym(Bool, True{}, False{}, e))
2668    case False{}:
2669      MBool.false_ne_true()(e)
2670
2671# Routing facts about hashes and a mask.
2672def h.u_ne0.c(
2673  +x: U32, +y: U32, e1: {U32.is_eq(x, y) == False{} : Bool}, e2: {U32.is_eq(x, 0) == True{} : Bool},
2674  b: Bool, eb: {b == U32.is_eq(y, 0) : Bool}
2675) -> {b == False{} : Bool}:
2676  match b:
2677    case True{}:
2678      h.tf({True{} == False{} : Bool}, U32.is_eq(x, y),
2679        rw(U32, z => {U32.is_eq(x, z) == True{} : Bool}, y, 0,
2680          h.u_sound(y, 0, h.sb(True{}, U32.is_eq(y, 0), eb)), e2),
2681        e1)
2682    case False{}:
2683      {==}
2684
2685def h.u_ne0(
2686  +x: U32, +y: U32, e1: {U32.is_eq(x, y) == False{} : Bool}, e2: {U32.is_eq(x, 0) == True{} : Bool}
2687) -> {U32.is_eq(y, 0) == False{} : Bool}:
2688  h.u_ne0.c(x, y, e1, e2, U32.is_eq(y, 0), {==})
2689
2690def h.u_route_t.c(
2691  +o: U32, +hk: U32, +mask: U32, ob: {h.onebit(mask) == True{} : Bool},
2692  e1: {U32.is_eq((o .&. mask : U32), (hk .&. mask : U32)) == False{} : Bool},
2693  e2: {U32.is_eq((o .&. mask : U32), 0) == False{} : Bool},
2694  b: Bool, eb: {b == U32.is_eq((hk .&. mask : U32), 0) : Bool}
2695) -> {b == True{} : Bool}:
2696  match b:
2697    case True{}:
2698      {==}
2699    case False{}:
2700      h.tf({False{} == True{} : Bool}, U32.is_eq((o .&. mask : U32), (hk .&. mask : U32)),
2701        h.route(o, hk, mask, ob, e2, h.sb(False{}, U32.is_eq((hk .&. mask : U32), 0), eb)),
2702        e1)
2703
2704def h.u_route_t(
2705  +o: U32, +hk: U32, +mask: U32, ob: {h.onebit(mask) == True{} : Bool},
2706  e1: {U32.is_eq((o .&. mask : U32), (hk .&. mask : U32)) == False{} : Bool},
2707  e2: {U32.is_eq((o .&. mask : U32), 0) == False{} : Bool}
2708) -> {U32.is_eq((hk .&. mask : U32), 0) == True{} : Bool}:
2709  h.u_route_t.c(o, hk, mask, ob, e1, e2, U32.is_eq((hk .&. mask : U32), 0), {==})
2710
2711def h.u_same0(
2712  +o: U32, +hk: U32, +mask: U32, -c: Bool,
2713  e1: {U32.is_eq((o .&. mask : U32), (hk .&. mask : U32)) == True{} : Bool},
2714  e2: {U32.is_eq((o .&. mask : U32), 0) == c : Bool}
2715) -> {U32.is_eq((hk .&. mask : U32), 0) == c : Bool}:
2716  rw(U32, z => {U32.is_eq(z, 0) == c : Bool}, (hk .&. mask : U32), (o .&. mask : U32),
2717    Equal.sym(U32, (o .&. mask : U32), (hk .&. mask : U32),
2718      h.u_sound((o .&. mask : U32), (hk .&. mask : U32), e1)),
2719    e2)
2720
2721def h.u_diff.c(
2722  +o: U32, +hk: U32, +mask: U32, +c: Bool,
2723  e2: {U32.is_eq((o .&. mask : U32), 0) == c : Bool},
2724  ed: {U32.is_eq((hk .&. mask : U32), 0) == Bool.not(c) : Bool},
2725  b: Bool, eb: {b == U32.is_eq(o, hk) : Bool}
2726) -> {b == False{} : Bool}:
2727  match b:
2728    case True{}:
2729      +e3 = rw(U32, z => {U32.is_eq((z .&. mask : U32), 0) == c : Bool}, hk, o,
2730        Equal.sym(U32, o, hk, h.u_sound(o, hk, h.sb(True{}, U32.is_eq(o, hk), eb))), e2)
2731      Empty.absurd({True{} == False{} : Bool}, h.cnc(c, Equal.trans(Bool, c, U32.is_eq((hk .&. mask : U32), 0), Bool.not(c),
2732          Equal.sym(Bool, U32.is_eq((hk .&. mask : U32), 0), c, e3), ed)))
2733    case False{}:
2734      {==}
2735
2736def h.u_diff(
2737  +o: U32, +hk: U32, +mask: U32, +c: Bool,
2738  e2: {U32.is_eq((o .&. mask : U32), 0) == c : Bool},
2739  ed: {U32.is_eq((hk .&. mask : U32), 0) == Bool.not(c) : Bool}
2740) -> {U32.is_eq(o, hk) == False{} : Bool}:
2741  h.u_diff.c(o, hk, mask, c, e2, ed, U32.is_eq(o, hk), {==})
2742
2743# Unfolding get.go by a known test, simple side first.
2744def h.g_lo(
2745  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +p: Nat, +mask: U32, +lo: M.HMap<K, V>,
2746  +hi: M.HMap<K, V>, +hk: U32, +k: K, e: {U32.is_eq((hk .&. mask : U32), 0) == True{} : Bool}
2747) -> {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k)
2748      == h.G(~K, ~V, ~eq, 1n+p, mask, M.HBranch{lo, hi}, hk, k) : Maybe<&2, V>}:
2749  %h.sb(U32.is_eq((hk .&. mask : U32), 0), True{}, e)
2750    : {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k)
2751       == M.HMap.bool(Maybe<&2, V>, _, u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k),
2752         u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)) : Maybe<&2, V>}
2753  {==}
2754
2755def h.g_hi(
2756  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +p: Nat, +mask: U32, +lo: M.HMap<K, V>,
2757  +hi: M.HMap<K, V>, +hk: U32, +k: K, e: {U32.is_eq((hk .&. mask : U32), 0) == False{} : Bool}
2758) -> {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)
2759      == h.G(~K, ~V, ~eq, 1n+p, mask, M.HBranch{lo, hi}, hk, k) : Maybe<&2, V>}:
2760  %h.sb(U32.is_eq((hk .&. mask : U32), 0), False{}, e)
2761    : {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)
2762       == M.HMap.bool(Maybe<&2, V>, _, u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k),
2763         u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)) : Maybe<&2, V>}
2764  {==}
2765
2766def h.g_lf_t(
2767  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +p: Nat, +mask: U32, +o: U32,
2768  +es: List<&2, M.Entry<K, V>>, +hk: U32, +k: K, e: {U32.is_eq(o, hk) == True{} : Bool}
2769) -> {h.EG(~K, ~V, ~eq, es, k) == h.G(~K, ~V, ~eq, 1n+p, mask, M.HLeaf{o, es}, hk, k) : Maybe<&2, V>}:
2770  %h.sb(U32.is_eq(o, hk), True{}, e)
2771    : {h.EG(~K, ~V, ~eq, es, k)
2772       == M.HMap.bool(Maybe<&2, V>, _, u => h.EG(~K, ~V, ~eq, es, k), u => None{}) : Maybe<&2, V>}
2773  {==}
2774
2775def h.gnil(~K: Data, ~V: Data, ~eq: K -> K -> Bool, n: Nat, +mask: U32, +hk: U32, +k: K)
2776  -> {h.G(~K, ~V, ~eq, n, mask, M.HNil{}, hk, k) == None{} : Maybe<&2, V>}:
2777  match n:
2778    case 0n:
2779      {==}
2780    case 1n+p:
2781      {==}
2782
2783def h.g_nil_leaf(~K: Data, ~V: Data, ~eq: K -> K -> Bool, n: Nat, +mask: U32, +o: U32, +hk: U32, +k: K)
2784  -> {h.G(~K, ~V, ~eq, n, mask, M.HLeaf{o, Nil{}}, hk, k) == h.G(~K, ~V, ~eq, n, mask, M.HNil{}, hk, k) : Maybe<&2, V>}:
2785  match n:
2786    case 0n:
2787      {==}
2788    case 1n+p:
2789      h.bool_none(V, U32.is_eq(o, hk), None{}, {==})
2790
2791def h.get_leaf(
2792  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +n: Nat, +mask: U32, +o: U32,
2793  xs: List<&2, M.Entry<K, V>>, +hk: U32, +k: K
2794) -> {h.G(~K, ~V, ~eq, n, mask, M.HLeaf{o, xs}, hk, k)
2795      == h.G(~K, ~V, ~eq, n, mask, M.HMap.leaf(K, V, o, xs), hk, k) : Maybe<&2, V>}:
2796  match xs:
2797    case Nil{}:
2798      h.g_nil_leaf(~K, ~V, ~eq, n, mask, o, hk, k)
2799    case Con{e, rest}:
2800      {==}
2801
2802def h.size_leaf(-K: Data, -V: Data, +o: U32, xs: List<&2, M.Entry<K, V>>)
2803  -> {h.len(K, V, xs) == h.Sz(K, V, M.HMap.leaf(K, V, o, xs)) : Nat}:
2804  match xs:
2805    case Nil{}:
2806      {==}
2807    case Con{e, rest}:
2808      {==}
2809
2810def h.get_join(
2811  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +p: Nat, +mask: U32, lo: M.HMap<K, V>,
2812  hi: M.HMap<K, V>, +hk: U32, +k: K
2813) -> {h.G(~K, ~V, ~eq, 1n+p, mask, M.HBranch{lo, hi}, hk, k)
2814      == h.G(~K, ~V, ~eq, 1n+p, mask, M.HMap.join(K, V, lo, hi), hk, k) : Maybe<&2, V>}:
2815  match lo:
2816    case M.HNil{}:
2817      match hi:
2818        case M.HNil{}:
2819          Equal.sym(Maybe<&2, V>, None{},
2820            M.HMap.bool(Maybe<&2, V>, U32.is_eq((hk .&. mask : U32), 0),
2821              u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), M.HNil{}, hk, k),
2822              u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), M.HNil{}, hk, k)),
2823            h.bnn(V, U32.is_eq((hk .&. mask : U32), 0),
2824              h.G(~K, ~V, ~eq, p, (mask << 1n : U32), M.HNil{}, hk, k),
2825              h.gnil(~K, ~V, ~eq, p, (mask << 1n : U32), hk, k)))
2826        case M.HLeaf{a, b}:
2827          {==}
2828        case M.HBranch{a, b}:
2829          {==}
2830    case M.HLeaf{a, b}:
2831      {==}
2832    case M.HBranch{a, b}:
2833      {==}
2834
2835def h.size_join(-K: Data, -V: Data, lo: M.HMap<K, V>, hi: M.HMap<K, V>)
2836  -> {Nat.add(h.Sz(K, V, lo), h.Sz(K, V, hi)) == h.Sz(K, V, M.HMap.join(K, V, lo, hi)) : Nat}:
2837  match lo:
2838    case M.HNil{}:
2839      match hi:
2840        case M.HNil{}:
2841          {==}
2842        case M.HLeaf{a, b}:
2843          {==}
2844        case M.HBranch{a, b}:
2845          {==}
2846    case M.HLeaf{a, b}:
2847      {==}
2848    case M.HBranch{a, b}:
2849      {==}
2850
2851def h.wf_nil(~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool, n: Nat)
2852  -> {h.WF(~K, ~V, ~hash, ~eq, n, M.HNil{}) == True{} : Bool}:
2853  match n:
2854    case 0n:
2855      {==}
2856    case 1n+p:
2857      {==}
2858
2859def h.wf_leaf(
2860  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool, +n: Nat, +o: U32,
2861  xs: List<&2, M.Entry<K, V>>, w: {h.WF(~K, ~V, ~hash, ~eq, n, M.HLeaf{o, xs}) == True{} : Bool}
2862) -> {h.WF(~K, ~V, ~hash, ~eq, n, M.HMap.leaf(K, V, o, xs)) == True{} : Bool}:
2863  match xs:
2864    case Nil{}:
2865      h.wf_nil(~K, ~V, ~hash, ~eq, n)
2866    case Con{e, rest}:
2867      w
2868
2869def h.wf_join(
2870  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool, +p: Nat, lo: M.HMap<K, V>,
2871  hi: M.HMap<K, V>, wl: {h.WF(~K, ~V, ~hash, ~eq, p, lo) == True{} : Bool},
2872  wh: {h.WF(~K, ~V, ~hash, ~eq, p, hi) == True{} : Bool}
2873) -> {h.WF(~K, ~V, ~hash, ~eq, 1n+p, M.HMap.join(K, V, lo, hi)) == True{} : Bool}:
2874  match lo:
2875    case M.HNil{}:
2876      match hi:
2877        case M.HNil{}:
2878          {==}
2879        case M.HLeaf{+a, +b}:
2880          MBool.and_eq_true(h.WF(~K, ~V, ~hash, ~eq, p, M.HNil{}), h.WF(~K, ~V, ~hash, ~eq, p, M.HLeaf{a, b}), wl, wh)
2881        case M.HBranch{+a, +b}:
2882          MBool.and_eq_true(h.WF(~K, ~V, ~hash, ~eq, p, M.HNil{}), h.WF(~K, ~V, ~hash, ~eq, p, M.HBranch{a, b}), wl, wh)
2883    case M.HLeaf{+a, +b}:
2884      MBool.and_eq_true(h.WF(~K, ~V, ~hash, ~eq, p, M.HLeaf{a, b}), h.WF(~K, ~V, ~hash, ~eq, p, hi), wl, wh)
2885    case M.HBranch{+a, +b}:
2886      MBool.and_eq_true(h.WF(~K, ~V, ~hash, ~eq, p, M.HBranch{a, b}), h.WF(~K, ~V, ~hash, ~eq, p, hi), wl, wh)
2887
2888# get after put, same key.
2889def h.fresh_get(
2890  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, ~refl: @x: K -> {eq(x, x) == True{} : Bool},
2891  p: Nat, +mm: U32, +hk: U32, +k: K, +v: V
2892) -> {h.G(~K, ~V, ~eq, p, mm, M.HLeaf{hk, [M.Entry{k, v}]}, hk, k) == Some{v} : Maybe<&2, V>}:
2893  match p:
2894    case 0n:
2895      h.eg_put_same(~K, ~V, ~eq, ~refl, Nil{}, k, v)
2896    case 1n+q:
2897      %h.g_lf_t(~K, ~V, ~eq, q, mm, hk, [M.Entry{k, v}], hk, k, h.u_refl(hk)) : {_ == Some{v} : Maybe<&2, V>}
2898      h.eg_put_same(~K, ~V, ~eq, ~refl, Nil{}, k, v)
2899
2900def h.split_same.b(
2901  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +p: Nat, +mask: U32, +o: U32,
2902  +es: List<&2, M.Entry<K, V>>, +hk: U32, +k: K, +v: V, ob: {h.onebit(mask) == True{} : Bool},
2903  b1: Bool, b2: Bool,
2904  e1: {b1 == U32.is_eq((o .&. mask : U32), (hk .&. mask : U32)) : Bool},
2905  e2: {b2 == U32.is_eq((o .&. mask : U32), 0) : Bool},
2906  ih: {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), h.S(~K, ~V, ~eq, p, (mask << 1n : U32), o, es, hk, k, v), hk, k) == Some{v} : Maybe<&2, V>},
2907  fr: {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), M.HLeaf{hk, [M.Entry{k, v}]}, hk, k) == Some{v} : Maybe<&2, V>}
2908) -> {h.G(~K, ~V, ~eq, 1n+p, mask, h.sp(~K, ~V, ~eq, b1, b2, p, mask, o, es, hk, k, v), hk, k) == Some{v} : Maybe<&2, V>}:
2909  match b1 b2:
2910    case True{} True{}:
2911      %h.g_lo(~K, ~V, ~eq, p, mask, h.S(~K, ~V, ~eq, p, (mask << 1n : U32), o, es, hk, k, v), M.HNil{}, hk, k,
2912        h.u_same0(o, hk, mask, True{},
2913          h.sb(True{}, U32.is_eq((o .&. mask : U32), (hk .&. mask : U32)), e1),
2914          h.sb(True{}, U32.is_eq((o .&. mask : U32), 0), e2)))
2915        : {_ == Some{v} : Maybe<&2, V>}
2916      ih
2917    case True{} False{}:
2918      %h.g_hi(~K, ~V, ~eq, p, mask, M.HNil{}, h.S(~K, ~V, ~eq, p, (mask << 1n : U32), o, es, hk, k, v), hk, k,
2919        h.u_same0(o, hk, mask, False{},
2920          h.sb(True{}, U32.is_eq((o .&. mask : U32), (hk .&. mask : U32)), e1),
2921          h.sb(False{}, U32.is_eq((o .&. mask : U32), 0), e2)))
2922        : {_ == Some{v} : Maybe<&2, V>}
2923      ih
2924    case False{} True{}:
2925      %h.g_hi(~K, ~V, ~eq, p, mask, M.HLeaf{o, es}, M.HLeaf{hk, [M.Entry{k, v}]}, hk, k,
2926        h.u_ne0((o .&. mask : U32), (hk .&. mask : U32),
2927          h.sb(False{}, U32.is_eq((o .&. mask : U32), (hk .&. mask : U32)), e1),
2928          h.sb(True{}, U32.is_eq((o .&. mask : U32), 0), e2)))
2929        : {_ == Some{v} : Maybe<&2, V>}
2930      fr
2931    case False{} False{}:
2932      %h.g_lo(~K, ~V, ~eq, p, mask, M.HLeaf{hk, [M.Entry{k, v}]}, M.HLeaf{o, es}, hk, k,
2933        h.u_route_t(o, hk, mask, ob,
2934          h.sb(False{}, U32.is_eq((o .&. mask : U32), (hk .&. mask : U32)), e1),
2935          h.sb(False{}, U32.is_eq((o .&. mask : U32), 0), e2)))
2936        : {_ == Some{v} : Maybe<&2, V>}
2937      fr
2938
2939def h.split_same(
2940  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, ~refl: @x: K -> {eq(x, x) == True{} : Bool},
2941  n: Nat, +mask: U32, +o: U32, +es: List<&2, M.Entry<K, V>>, +hk: U32, +k: K, +v: V,
2942  +ob: {h.onebit(mask) == True{} : Bool}
2943) -> {h.G(~K, ~V, ~eq, n, mask, h.S(~K, ~V, ~eq, n, mask, o, es, hk, k, v), hk, k) == Some{v} : Maybe<&2, V>}:
2944  match n:
2945    case 0n:
2946      h.eg_put_same(~K, ~V, ~eq, ~refl, es, k, v)
2947    case 1n+(+p):
2948      h.split_same.b(~K, ~V, ~eq, p, mask, o, es, hk, k, v, ob,
2949        U32.is_eq((o .&. mask : U32), (hk .&. mask : U32)), U32.is_eq((o .&. mask : U32), 0), {==}, {==},
2950        h.split_same(~K, ~V, ~eq, ~refl, p, (mask << 1n : U32), o, es, hk, k, v, h.onebit_shl(mask, ob)),
2951        h.fresh_get(~K, ~V, ~eq, ~refl, p, (mask << 1n : U32), hk, k, v))
2952
2953def h.gp_same.lf(
2954  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, ~refl: @x: K -> {eq(x, x) == True{} : Bool},
2955  +p: Nat, +mask: U32, +o: U32, +es: List<&2, M.Entry<K, V>>, +hk: U32, +k: K, +v: V,
2956  b: Bool, eb: {b == U32.is_eq(o, hk) : Bool},
2957  sp: {h.G(~K, ~V, ~eq, 1n+p, mask, h.S(~K, ~V, ~eq, 1n+p, mask, o, es, hk, k, v), hk, k) == Some{v} : Maybe<&2, V>}
2958) -> {h.G(~K, ~V, ~eq, 1n+p, mask, h.pl(~K, ~V, ~eq, b, p, mask, o, es, hk, k, v), hk, k) == Some{v} : Maybe<&2, V>}:
2959  match b:
2960    case True{}:
2961      %h.g_lf_t(~K, ~V, ~eq, p, mask, o, M.HMap.entries.put(~K, ~V, ~eq, es, k, v), hk, k,
2962        h.sb(True{}, U32.is_eq(o, hk), eb)) : {_ == Some{v} : Maybe<&2, V>}
2963      h.eg_put_same(~K, ~V, ~eq, ~refl, es, k, v)
2964    case False{}:
2965      sp
2966
2967def h.gp_same.br(
2968  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +p: Nat, +mask: U32, +lo: M.HMap<K, V>,
2969  +hi: M.HMap<K, V>, +hk: U32, +k: K, +v: V,
2970  b: Bool, eb: {b == U32.is_eq((hk .&. mask : U32), 0) : Bool},
2971  il: {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), h.P(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k, v), hk, k) == Some{v} : Maybe<&2, V>},
2972  ih: {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), h.P(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k, v), hk, k) == Some{v} : Maybe<&2, V>}
2973) -> {h.G(~K, ~V, ~eq, 1n+p, mask, h.pb(~K, ~V, ~eq, b, p, mask, lo, hi, hk, k, v), hk, k) == Some{v} : Maybe<&2, V>}:
2974  match b:
2975    case True{}:
2976      %h.g_lo(~K, ~V, ~eq, p, mask, h.P(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k, v), hi, hk, k,
2977        h.sb(True{}, U32.is_eq((hk .&. mask : U32), 0), eb)) : {_ == Some{v} : Maybe<&2, V>}
2978      il
2979    case False{}:
2980      %h.g_hi(~K, ~V, ~eq, p, mask, lo, h.P(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k, v), hk, k,
2981        h.sb(False{}, U32.is_eq((hk .&. mask : U32), 0), eb)) : {_ == Some{v} : Maybe<&2, V>}
2982      ih
2983
2984def h.gp_same(
2985  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool, ~refl: @x: K -> {eq(x, x) == True{} : Bool},
2986  n: Nat, +mask: U32, m: M.HMap<K, V>, +hk: U32, +k: K, +v: V,
2987  +ob: {h.onebit(mask) == True{} : Bool}, +wf: {h.WF(~K, ~V, ~hash, ~eq, n, m) == True{} : Bool}
2988) -> {h.G(~K, ~V, ~eq, n, mask, h.P(~K, ~V, ~eq, n, mask, m, hk, k, v), hk, k) == Some{v} : Maybe<&2, V>}:
2989  match n:
2990    case 0n:
2991      match m:
2992        case M.HNil{}:
2993          h.eg_put_same(~K, ~V, ~eq, ~refl, Nil{}, k, v)
2994        case M.HLeaf{o, es}:
2995          h.eg_put_same(~K, ~V, ~eq, ~refl, es, k, v)
2996        case M.HBranch{lo, hi}:
2997          Empty.absurd({h.G(~K, ~V, ~eq, 0n, mask, M.HBranch{lo, hi}, hk, k) == Some{v} : Maybe<&2, V>}, MBool.false_ne_true()(wf))
2998    case 1n+(+p):
2999      match m:
3000        case M.HNil{}:
3001          %h.g_lf_t(~K, ~V, ~eq, p, mask, hk, [M.Entry{k, v}], hk, k, h.u_refl(hk)) : {_ == Some{v} : Maybe<&2, V>}
3002          h.eg_put_same(~K, ~V, ~eq, ~refl, Nil{}, k, v)
3003        case M.HLeaf{+o, +es}:
3004          h.gp_same.lf(~K, ~V, ~eq, ~refl, p, mask, o, es, hk, k, v, U32.is_eq(o, hk), {==},
3005            h.split_same(~K, ~V, ~eq, ~refl, 1n+p, mask, o, es, hk, k, v, ob))
3006        case M.HBranch{+lo, +hi}:
3007          h.gp_same.br(~K, ~V, ~eq, p, mask, lo, hi, hk, k, v, U32.is_eq((hk .&. mask : U32), 0), {==},
3008            h.gp_same(~K, ~V, ~hash, ~eq, ~refl, p, (mask << 1n : U32), lo, hk, k, v, h.onebit_shl(mask, ob),
3009              MBool.eq_true_of_and_left(h.WF(~K, ~V, ~hash, ~eq, p, lo), h.WF(~K, ~V, ~hash, ~eq, p, hi), wf)),
3010            h.gp_same(~K, ~V, ~hash, ~eq, ~refl, p, (mask << 1n : U32), hi, hk, k, v, h.onebit_shl(mask, ob),
3011              MBool.eq_true_of_and_right(h.WF(~K, ~V, ~hash, ~eq, p, lo), h.WF(~K, ~V, ~hash, ~eq, p, hi), wf)))
3012
3013# get after put, other key.
3014def h.r_eg.c(
3015  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool,
3016  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
3017  +o: U32, +es: List<&2, M.Entry<K, V>>, +k: K,
3018  hs: {Laws.hmap_hashed(~K, ~V, ~hash, es, o) == True{} : Bool},
3019  b: Bool, eb: {b == U32.is_eq(o, hash(k)) : Bool}
3020) -> {h.EG(~K, ~V, ~eq, es, k)
3021      == M.HMap.bool(Maybe<&2, V>, b, u => h.EG(~K, ~V, ~eq, es, k), u => None{}) : Maybe<&2, V>}:
3022  match b:
3023    case True{}:
3024      {==}
3025    case False{}:
3026      h.eg_none_hashed(~K, ~V, ~hash, ~eq, ~sound, es, o, k, h.sb(False{}, U32.is_eq(o, hash(k)), eb), hs)
3027
3028def h.r_eg(
3029  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool,
3030  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
3031  +o: U32, +es: List<&2, M.Entry<K, V>>, +k: K,
3032  hs: {Laws.hmap_hashed(~K, ~V, ~hash, es, o) == True{} : Bool}
3033) -> {h.EG(~K, ~V, ~eq, es, k) == h.R(~K, ~V, ~hash, ~eq, o, es, k) : Maybe<&2, V>}:
3034  h.r_eg.c(~K, ~V, ~hash, ~eq, ~sound, o, es, k, hs, U32.is_eq(o, hash(k)), {==})
3035
3036def h.r_none(
3037  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool, +o: U32,
3038  +es: List<&2, M.Entry<K, V>>, +k: K, ne: {U32.is_eq(o, hash(k)) == False{} : Bool}
3039) -> {None{} == h.R(~K, ~V, ~hash, ~eq, o, es, k) : Maybe<&2, V>}:
3040  %h.sb(U32.is_eq(o, hash(k)), False{}, ne)
3041    : {None{} == M.HMap.bool(Maybe<&2, V>, _, u => h.EG(~K, ~V, ~eq, es, k), u => None{}) : Maybe<&2, V>}
3042  {==}
3043
3044def h.g_leaf_r(
3045  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool,
3046  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
3047  p: Nat, +mm: U32, +o: U32, +es: List<&2, M.Entry<K, V>>, +k: K,
3048  hs: {Laws.hmap_hashed(~K, ~V, ~hash, es, o) == True{} : Bool}
3049) -> {h.G(~K, ~V, ~eq, p, mm, M.HLeaf{o, es}, hash(k), k) == h.R(~K, ~V, ~hash, ~eq, o, es, k) : Maybe<&2, V>}:
3050  match p:
3051    case 0n:
3052      h.r_eg(~K, ~V, ~hash, ~eq, ~sound, o, es, k, hs)
3053    case 1n+q:
3054      {==}
3055
3056def h.g_fresh_none(
3057  ~K: Data, ~V: Data, ~eq: K -> K -> Bool,
3058  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
3059  p: Nat, +mm: U32, +h2: U32, +k2: K, +hk: U32, +k: K, +v: V, +nk: {eq(k, k2) == False{} : Bool}
3060) -> {h.G(~K, ~V, ~eq, p, mm, M.HLeaf{h2, [M.Entry{k2, v}]}, hk, k) == None{} : Maybe<&2, V>}:
3061  match p:
3062    case 0n:
3063      h.eg_put_other(~K, ~V, ~eq, ~sound, Nil{}, k2, k, v, nk)
3064    case 1n+q:
3065      h.bool_none(V, U32.is_eq(h2, hk), h.EG(~K, ~V, ~eq, [M.Entry{k2, v}], k),
3066        h.eg_put_other(~K, ~V, ~eq, ~sound, Nil{}, k2, k, v, nk))
3067
3068def h.split_other.b(
3069  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool,
3070  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
3071  +p: Nat, +mask: U32, +o: U32, +es: List<&2, M.Entry<K, V>>, +h2: U32, +k2: K, +k: K, +v: V,
3072  +hs: {Laws.hmap_hashed(~K, ~V, ~hash, es, o) == True{} : Bool},
3073  +nk: {eq(k, k2) == False{} : Bool},
3074  b1: Bool, b2: Bool,
3075  e2: {b2 == U32.is_eq((o .&. mask : U32), 0) : Bool},
3076  ih: {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), h.S(~K, ~V, ~eq, p, (mask << 1n : U32), o, es, h2, k2, v), hash(k), k)
3077       == h.R(~K, ~V, ~hash, ~eq, o, es, k) : Maybe<&2, V>}
3078) -> {h.G(~K, ~V, ~eq, 1n+p, mask, h.sp(~K, ~V, ~eq, b1, b2, p, mask, o, es, h2, k2, v), hash(k), k)
3079      == h.R(~K, ~V, ~hash, ~eq, o, es, k) : Maybe<&2, V>}:
3080  match b1 b2:
3081    case True{} True{}:
3082      +mm = (mask << 1n : U32)
3083      +d = U32.is_eq((hash(k) .&. mask : U32), 0)
3084      +sub = h.S(~K, ~V, ~eq, p, mm, o, es, h2, k2, v)
3085      +old = {M.HLeaf{o, es} : M.HMap<K, V>}
3086      +fresh = {M.HLeaf{h2, [M.Entry{k2, v}]} : M.HMap<K, V>}
3087      +r = h.R(~K, ~V, ~hash, ~eq, o, es, k)
3088      h.bsel(Maybe<&2, V>, d, h.G(~K, ~V, ~eq, p, mm, sub, hash(k), k),
3089        h.G(~K, ~V, ~eq, p, mm, M.HNil{}, hash(k), k), r,
3090        ed => ih,
3091        ed => Equal.trans(Maybe<&2, V>, h.G(~K, ~V, ~eq, p, mm, M.HNil{}, hash(k), k), None{}, r,
3092          h.gnil(~K, ~V, ~eq, p, mm, hash(k), k),
3093          h.r_none(~K, ~V, ~hash, ~eq, o, es, k,
3094            h.u_diff(o, hash(k), mask, True{}, h.sb(True{}, U32.is_eq((o .&. mask : U32), 0), e2), ed))))
3095    case True{} False{}:
3096      +mm = (mask << 1n : U32)
3097      +d = U32.is_eq((hash(k) .&. mask : U32), 0)
3098      +sub = h.S(~K, ~V, ~eq, p, mm, o, es, h2, k2, v)
3099      +old = {M.HLeaf{o, es} : M.HMap<K, V>}
3100      +fresh = {M.HLeaf{h2, [M.Entry{k2, v}]} : M.HMap<K, V>}
3101      +r = h.R(~K, ~V, ~hash, ~eq, o, es, k)
3102      h.bsel(Maybe<&2, V>, d, h.G(~K, ~V, ~eq, p, mm, M.HNil{}, hash(k), k),
3103        h.G(~K, ~V, ~eq, p, mm, sub, hash(k), k), r,
3104        ed => Equal.trans(Maybe<&2, V>, h.G(~K, ~V, ~eq, p, mm, M.HNil{}, hash(k), k), None{}, r,
3105          h.gnil(~K, ~V, ~eq, p, mm, hash(k), k),
3106          h.r_none(~K, ~V, ~hash, ~eq, o, es, k,
3107            h.u_diff(o, hash(k), mask, False{}, h.sb(False{}, U32.is_eq((o .&. mask : U32), 0), e2), ed))),
3108        ed => ih)
3109    case False{} True{}:
3110      +mm = (mask << 1n : U32)
3111      +d = U32.is_eq((hash(k) .&. mask : U32), 0)
3112      +sub = h.S(~K, ~V, ~eq, p, mm, o, es, h2, k2, v)
3113      +old = {M.HLeaf{o, es} : M.HMap<K, V>}
3114      +fresh = {M.HLeaf{h2, [M.Entry{k2, v}]} : M.HMap<K, V>}
3115      +r = h.R(~K, ~V, ~hash, ~eq, o, es, k)
3116      h.bsel(Maybe<&2, V>, d, h.G(~K, ~V, ~eq, p, mm, old, hash(k), k),
3117        h.G(~K, ~V, ~eq, p, mm, fresh, hash(k), k), r,
3118        ed => h.g_leaf_r(~K, ~V, ~hash, ~eq, ~sound, p, mm, o, es, k, hs),
3119        ed => Equal.trans(Maybe<&2, V>, h.G(~K, ~V, ~eq, p, mm, fresh, hash(k), k), None{}, r,
3120          h.g_fresh_none(~K, ~V, ~eq, ~sound, p, mm, h2, k2, hash(k), k, v, nk),
3121          h.r_none(~K, ~V, ~hash, ~eq, o, es, k,
3122            h.u_diff(o, hash(k), mask, True{}, h.sb(True{}, U32.is_eq((o .&. mask : U32), 0), e2), ed))))
3123    case False{} False{}:
3124      +mm = (mask << 1n : U32)
3125      +d = U32.is_eq((hash(k) .&. mask : U32), 0)
3126      +sub = h.S(~K, ~V, ~eq, p, mm, o, es, h2, k2, v)
3127      +old = {M.HLeaf{o, es} : M.HMap<K, V>}
3128      +fresh = {M.HLeaf{h2, [M.Entry{k2, v}]} : M.HMap<K, V>}
3129      +r = h.R(~K, ~V, ~hash, ~eq, o, es, k)
3130      h.bsel(Maybe<&2, V>, d, h.G(~K, ~V, ~eq, p, mm, fresh, hash(k), k),
3131        h.G(~K, ~V, ~eq, p, mm, old, hash(k), k), r,
3132        ed => Equal.trans(Maybe<&2, V>, h.G(~K, ~V, ~eq, p, mm, fresh, hash(k), k), None{}, r,
3133          h.g_fresh_none(~K, ~V, ~eq, ~sound, p, mm, h2, k2, hash(k), k, v, nk),
3134          h.r_none(~K, ~V, ~hash, ~eq, o, es, k,
3135            h.u_diff(o, hash(k), mask, False{}, h.sb(False{}, U32.is_eq((o .&. mask : U32), 0), e2), ed))),
3136        ed => h.g_leaf_r(~K, ~V, ~hash, ~eq, ~sound, p, mm, o, es, k, hs))
3137
3138def h.split_other(
3139  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool,
3140  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
3141  n: Nat, +mask: U32, +o: U32, +es: List<&2, M.Entry<K, V>>, +h2: U32, +k2: K, +k: K, +v: V,
3142  +hs: {Laws.hmap_hashed(~K, ~V, ~hash, es, o) == True{} : Bool},
3143  +nk: {eq(k, k2) == False{} : Bool}
3144) -> {h.G(~K, ~V, ~eq, n, mask, h.S(~K, ~V, ~eq, n, mask, o, es, h2, k2, v), hash(k), k)
3145      == h.R(~K, ~V, ~hash, ~eq, o, es, k) : Maybe<&2, V>}:
3146  match n:
3147    case 0n:
3148      Equal.trans(Maybe<&2, V>, h.EG(~K, ~V, ~eq, M.HMap.entries.put(~K, ~V, ~eq, es, k2, v), k),
3149        h.EG(~K, ~V, ~eq, es, k), h.R(~K, ~V, ~hash, ~eq, o, es, k),
3150        h.eg_put_other(~K, ~V, ~eq, ~sound, es, k2, k, v, nk),
3151        h.r_eg(~K, ~V, ~hash, ~eq, ~sound, o, es, k, hs))
3152    case 1n+(+p):
3153      h.split_other.b(~K, ~V, ~hash, ~eq, ~sound, p, mask, o, es, h2, k2, k, v, hs, nk,
3154        U32.is_eq((o .&. mask : U32), (h2 .&. mask : U32)), U32.is_eq((o .&. mask : U32), 0), {==},
3155        h.split_other(~K, ~V, ~hash, ~eq, ~sound, p, (mask << 1n : U32), o, es, h2, k2, k, v, hs, nk))
3156
3157def h.gp_other.lf(
3158  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool,
3159  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
3160  +p: Nat, +mask: U32, +o: U32, +es: List<&2, M.Entry<K, V>>, +h2: U32, +k2: K, +k: K, +v: V,
3161  +nk: {eq(k, k2) == False{} : Bool}, b: Bool,
3162  sp: {h.G(~K, ~V, ~eq, 1n+p, mask, h.S(~K, ~V, ~eq, 1n+p, mask, o, es, h2, k2, v), hash(k), k)
3163       == h.G(~K, ~V, ~eq, 1n+p, mask, M.HLeaf{o, es}, hash(k), k) : Maybe<&2, V>}
3164) -> {h.G(~K, ~V, ~eq, 1n+p, mask, h.pl(~K, ~V, ~eq, b, p, mask, o, es, h2, k2, v), hash(k), k)
3165      == h.G(~K, ~V, ~eq, 1n+p, mask, M.HLeaf{o, es}, hash(k), k) : Maybe<&2, V>}:
3166  match b:
3167    case True{}:
3168      h.bool_l(Maybe<&2, V>, U32.is_eq(o, hash(k)),
3169        h.EG(~K, ~V, ~eq, M.HMap.entries.put(~K, ~V, ~eq, es, k2, v), k), h.EG(~K, ~V, ~eq, es, k), None{},
3170        h.eg_put_other(~K, ~V, ~eq, ~sound, es, k2, k, v, nk))
3171    case False{}:
3172      sp
3173
3174def h.gp_other.br(
3175  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +p: Nat, +mask: U32, +lo: M.HMap<K, V>,
3176  +hi: M.HMap<K, V>, +h2: U32, +k2: K, +hk: U32, +k: K, +v: V, b: Bool,
3177  il: {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), h.P(~K, ~V, ~eq, p, (mask << 1n : U32), lo, h2, k2, v), hk, k)
3178       == h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k) : Maybe<&2, V>},
3179  ih: {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), h.P(~K, ~V, ~eq, p, (mask << 1n : U32), hi, h2, k2, v), hk, k)
3180       == h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k) : Maybe<&2, V>}
3181) -> {h.G(~K, ~V, ~eq, 1n+p, mask, h.pb(~K, ~V, ~eq, b, p, mask, lo, hi, h2, k2, v), hk, k)
3182      == h.G(~K, ~V, ~eq, 1n+p, mask, M.HBranch{lo, hi}, hk, k) : Maybe<&2, V>}:
3183  match b:
3184    case True{}:
3185      h.bool_l(Maybe<&2, V>, U32.is_eq((hk .&. mask : U32), 0),
3186        h.G(~K, ~V, ~eq, p, (mask << 1n : U32), h.P(~K, ~V, ~eq, p, (mask << 1n : U32), lo, h2, k2, v), hk, k),
3187        h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k),
3188        h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k), il)
3189    case False{}:
3190      h.bool_r(Maybe<&2, V>, U32.is_eq((hk .&. mask : U32), 0),
3191        h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k),
3192        h.G(~K, ~V, ~eq, p, (mask << 1n : U32), h.P(~K, ~V, ~eq, p, (mask << 1n : U32), hi, h2, k2, v), hk, k),
3193        h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k), ih)
3194
3195def h.gp_other(
3196  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool,
3197  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
3198  n: Nat, +mask: U32, m: M.HMap<K, V>, +h2: U32, +k2: K, +k: K, +v: V,
3199  +wf: {h.WF(~K, ~V, ~hash, ~eq, n, m) == True{} : Bool}, +nk: {eq(k, k2) == False{} : Bool}
3200) -> {h.G(~K, ~V, ~eq, n, mask, h.P(~K, ~V, ~eq, n, mask, m, h2, k2, v), hash(k), k)
3201      == h.G(~K, ~V, ~eq, n, mask, m, hash(k), k) : Maybe<&2, V>}:
3202  match n:
3203    case 0n:
3204      match m:
3205        case M.HNil{}:
3206          h.eg_put_other(~K, ~V, ~eq, ~sound, Nil{}, k2, k, v, nk)
3207        case M.HLeaf{o, es}:
3208          h.eg_put_other(~K, ~V, ~eq, ~sound, es, k2, k, v, nk)
3209        case M.HBranch{lo, hi}:
3210          {==}
3211    case 1n+(+p):
3212      match m:
3213        case M.HNil{}:
3214          h.bool_none(V, U32.is_eq(h2, hash(k)), h.EG(~K, ~V, ~eq, [M.Entry{k2, v}], k),
3215            h.eg_put_other(~K, ~V, ~eq, ~sound, Nil{}, k2, k, v, nk))
3216        case M.HLeaf{+o, +es}:
3217          h.gp_other.lf(~K, ~V, ~hash, ~eq, ~sound, p, mask, o, es, h2, k2, k, v, nk, U32.is_eq(o, h2),
3218            h.split_other(~K, ~V, ~hash, ~eq, ~sound, 1n+p, mask, o, es, h2, k2, k, v,
3219              MBool.eq_true_of_and_left(Laws.hmap_hashed(~K, ~V, ~hash, es, o), Laws.hmap_distinct(~K, ~V, ~eq, es), wf), nk))
3220        case M.HBranch{+lo, +hi}:
3221          h.gp_other.br(~K, ~V, ~eq, p, mask, lo, hi, h2, k2, hash(k), k, v, U32.is_eq((h2 .&. mask : U32), 0),
3222            h.gp_other(~K, ~V, ~hash, ~eq, ~sound, p, (mask << 1n : U32), lo, h2, k2, k, v,
3223              MBool.eq_true_of_and_left(h.WF(~K, ~V, ~hash, ~eq, p, lo), h.WF(~K, ~V, ~hash, ~eq, p, hi), wf), nk),
3224            h.gp_other(~K, ~V, ~hash, ~eq, ~sound, p, (mask << 1n : U32), hi, h2, k2, k, v,
3225              MBool.eq_true_of_and_right(h.WF(~K, ~V, ~hash, ~eq, p, lo), h.WF(~K, ~V, ~hash, ~eq, p, hi), wf), nk))
3226
3227# get after del.
3228def h.gd_same.lf(
3229  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +p: Nat, +mask: U32, +o: U32,
3230  +es: List<&2, M.Entry<K, V>>, +hk: U32, +k: K, b: Bool, eb: {b == U32.is_eq(o, hk) : Bool},
3231  ed: {h.EG(~K, ~V, ~eq, M.HMap.entries.del(~K, ~V, ~eq, es, k), k) == None{} : Maybe<&2, V>}
3232) -> {h.G(~K, ~V, ~eq, 1n+p, mask, h.dl(~K, ~V, ~eq, b, o, es, k), hk, k) == None{} : Maybe<&2, V>}:
3233  match b:
3234    case True{}:
3235      %h.get_leaf(~K, ~V, ~eq, 1n+p, mask, o, M.HMap.entries.del(~K, ~V, ~eq, es, k), hk, k) : {_ == None{} : Maybe<&2, V>}
3236      h.bool_none(V, U32.is_eq(o, hk), h.EG(~K, ~V, ~eq, M.HMap.entries.del(~K, ~V, ~eq, es, k), k), ed)
3237    case False{}:
3238      %eb : {M.HMap.bool(Maybe<&2, V>, _, u => h.EG(~K, ~V, ~eq, es, k), u => None{}) == None{} : Maybe<&2, V>}
3239      {==}
3240
3241def h.gd_same.br(
3242  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +p: Nat, +mask: U32, +lo: M.HMap<K, V>,
3243  +hi: M.HMap<K, V>, +hk: U32, +k: K, b: Bool, eb: {b == U32.is_eq((hk .&. mask : U32), 0) : Bool},
3244  il: {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), h.D(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k), hk, k) == None{} : Maybe<&2, V>},
3245  ih: {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), h.D(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k), hk, k) == None{} : Maybe<&2, V>}
3246) -> {h.G(~K, ~V, ~eq, 1n+p, mask, h.db(~K, ~V, ~eq, b, p, mask, lo, hi, hk, k), hk, k) == None{} : Maybe<&2, V>}:
3247  match b:
3248    case True{}:
3249      +dlo = h.D(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k)
3250      +dhi = h.D(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)
3251      %h.get_join(~K, ~V, ~eq, p, mask, dlo, hi, hk, k) : {_ == None{} : Maybe<&2, V>}
3252      %h.g_lo(~K, ~V, ~eq, p, mask, dlo, hi, hk, k, h.sb(True{}, U32.is_eq((hk .&. mask : U32), 0), eb))
3253        : {_ == None{} : Maybe<&2, V>}
3254      il
3255    case False{}:
3256      +dlo = h.D(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k)
3257      +dhi = h.D(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)
3258      %h.get_join(~K, ~V, ~eq, p, mask, lo, dhi, hk, k) : {_ == None{} : Maybe<&2, V>}
3259      %h.g_hi(~K, ~V, ~eq, p, mask, lo, dhi, hk, k, h.sb(False{}, U32.is_eq((hk .&. mask : U32), 0), eb))
3260        : {_ == None{} : Maybe<&2, V>}
3261      ih
3262
3263def h.gd_same(
3264  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool,
3265  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
3266  n: Nat, +mask: U32, m: M.HMap<K, V>, +hk: U32, +k: K,
3267  +wf: {h.WF(~K, ~V, ~hash, ~eq, n, m) == True{} : Bool}
3268) -> {h.G(~K, ~V, ~eq, n, mask, h.D(~K, ~V, ~eq, n, mask, m, hk, k), hk, k) == None{} : Maybe<&2, V>}:
3269  match n:
3270    case 0n:
3271      match m:
3272        case M.HNil{}:
3273          {==}
3274        case M.HLeaf{+o, +es}:
3275          %h.get_leaf(~K, ~V, ~eq, 0n, mask, o, M.HMap.entries.del(~K, ~V, ~eq, es, k), hk, k) : {_ == None{} : Maybe<&2, V>}
3276          h.eg_del_same(~K, ~V, ~eq, ~sound, es, k, wf)
3277        case M.HBranch{lo, hi}:
3278          {==}
3279    case 1n+(+p):
3280      match m:
3281        case M.HNil{}:
3282          {==}
3283        case M.HLeaf{+o, +es}:
3284          h.gd_same.lf(~K, ~V, ~eq, p, mask, o, es, hk, k, U32.is_eq(o, hk), {==},
3285            h.eg_del_same(~K, ~V, ~eq, ~sound, es, k,
3286              MBool.eq_true_of_and_right(Laws.hmap_hashed(~K, ~V, ~hash, es, o), Laws.hmap_distinct(~K, ~V, ~eq, es), wf)))
3287        case M.HBranch{+lo, +hi}:
3288          h.gd_same.br(~K, ~V, ~eq, p, mask, lo, hi, hk, k, U32.is_eq((hk .&. mask : U32), 0), {==},
3289            h.gd_same(~K, ~V, ~hash, ~eq, ~sound, p, (mask << 1n : U32), lo, hk, k,
3290              MBool.eq_true_of_and_left(h.WF(~K, ~V, ~hash, ~eq, p, lo), h.WF(~K, ~V, ~hash, ~eq, p, hi), wf)),
3291            h.gd_same(~K, ~V, ~hash, ~eq, ~sound, p, (mask << 1n : U32), hi, hk, k,
3292              MBool.eq_true_of_and_right(h.WF(~K, ~V, ~hash, ~eq, p, lo), h.WF(~K, ~V, ~hash, ~eq, p, hi), wf)))
3293
3294def h.gd_other.lf(
3295  ~K: Data, ~V: Data, ~eq: K -> K -> Bool,
3296  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
3297  +p: Nat, +mask: U32, +o: U32, +es: List<&2, M.Entry<K, V>>, +k2: K, +hk: U32, +k: K,
3298  +nk: {eq(k, k2) == False{} : Bool}, b: Bool
3299) -> {h.G(~K, ~V, ~eq, 1n+p, mask, h.dl(~K, ~V, ~eq, b, o, es, k2), hk, k)
3300      == h.G(~K, ~V, ~eq, 1n+p, mask, M.HLeaf{o, es}, hk, k) : Maybe<&2, V>}:
3301  match b:
3302    case True{}:
3303      %h.get_leaf(~K, ~V, ~eq, 1n+p, mask, o, M.HMap.entries.del(~K, ~V, ~eq, es, k2), hk, k)
3304        : {_ == h.G(~K, ~V, ~eq, 1n+p, mask, M.HLeaf{o, es}, hk, k) : Maybe<&2, V>}
3305      h.bool_l(Maybe<&2, V>, U32.is_eq(o, hk),
3306        h.EG(~K, ~V, ~eq, M.HMap.entries.del(~K, ~V, ~eq, es, k2), k), h.EG(~K, ~V, ~eq, es, k), None{},
3307        h.eg_del_other(~K, ~V, ~eq, ~sound, es, k2, k, nk))
3308    case False{}:
3309      {==}
3310
3311def h.gd_other.br(
3312  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +p: Nat, +mask: U32, +lo: M.HMap<K, V>,
3313  +hi: M.HMap<K, V>, +h2: U32, +k2: K, +hk: U32, +k: K, b: Bool,
3314  il: {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), h.D(~K, ~V, ~eq, p, (mask << 1n : U32), lo, h2, k2), hk, k)
3315       == h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k) : Maybe<&2, V>},
3316  ih: {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), h.D(~K, ~V, ~eq, p, (mask << 1n : U32), hi, h2, k2), hk, k)
3317       == h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k) : Maybe<&2, V>}
3318) -> {h.G(~K, ~V, ~eq, 1n+p, mask, h.db(~K, ~V, ~eq, b, p, mask, lo, hi, h2, k2), hk, k)
3319      == h.G(~K, ~V, ~eq, 1n+p, mask, M.HBranch{lo, hi}, hk, k) : Maybe<&2, V>}:
3320  match b:
3321    case True{}:
3322      +dlo = h.D(~K, ~V, ~eq, p, (mask << 1n : U32), lo, h2, k2)
3323      +dhi = h.D(~K, ~V, ~eq, p, (mask << 1n : U32), hi, h2, k2)
3324      +d = U32.is_eq((hk .&. mask : U32), 0)
3325      %h.get_join(~K, ~V, ~eq, p, mask, dlo, hi, hk, k)
3326        : {_ == h.G(~K, ~V, ~eq, 1n+p, mask, M.HBranch{lo, hi}, hk, k) : Maybe<&2, V>}
3327      h.bool_l(Maybe<&2, V>, d, h.G(~K, ~V, ~eq, p, (mask << 1n : U32), dlo, hk, k),
3328        h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k), h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k), il)
3329    case False{}:
3330      +dlo = h.D(~K, ~V, ~eq, p, (mask << 1n : U32), lo, h2, k2)
3331      +dhi = h.D(~K, ~V, ~eq, p, (mask << 1n : U32), hi, h2, k2)
3332      +d = U32.is_eq((hk .&. mask : U32), 0)
3333      %h.get_join(~K, ~V, ~eq, p, mask, lo, dhi, hk, k)
3334        : {_ == h.G(~K, ~V, ~eq, 1n+p, mask, M.HBranch{lo, hi}, hk, k) : Maybe<&2, V>}
3335      h.bool_r(Maybe<&2, V>, d, h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k),
3336        h.G(~K, ~V, ~eq, p, (mask << 1n : U32), dhi, hk, k), h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k), ih)
3337
3338def h.gd_other(
3339  ~K: Data, ~V: Data, ~eq: K -> K -> Bool,
3340  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
3341  n: Nat, +mask: U32, m: M.HMap<K, V>, +h2: U32, +k2: K, +hk: U32, +k: K,
3342  +nk: {eq(k, k2) == False{} : Bool}
3343) -> {h.G(~K, ~V, ~eq, n, mask, h.D(~K, ~V, ~eq, n, mask, m, h2, k2), hk, k)
3344      == h.G(~K, ~V, ~eq, n, mask, m, hk, k) : Maybe<&2, V>}:
3345  match n:
3346    case 0n:
3347      match m:
3348        case M.HNil{}:
3349          {==}
3350        case M.HLeaf{+o, +es}:
3351          %h.get_leaf(~K, ~V, ~eq, 0n, mask, o, M.HMap.entries.del(~K, ~V, ~eq, es, k2), hk, k)
3352            : {_ == h.EG(~K, ~V, ~eq, es, k) : Maybe<&2, V>}
3353          h.eg_del_other(~K, ~V, ~eq, ~sound, es, k2, k, nk)
3354        case M.HBranch{lo, hi}:
3355          {==}
3356    case 1n+(+p):
3357      match m:
3358        case M.HNil{}:
3359          {==}
3360        case M.HLeaf{+o, +es}:
3361          h.gd_other.lf(~K, ~V, ~eq, ~sound, p, mask, o, es, k2, hk, k, nk, U32.is_eq(o, h2))
3362        case M.HBranch{+lo, +hi}:
3363          h.gd_other.br(~K, ~V, ~eq, p, mask, lo, hi, h2, k2, hk, k, U32.is_eq((h2 .&. mask : U32), 0),
3364            h.gd_other(~K, ~V, ~eq, ~sound, p, (mask << 1n : U32), lo, h2, k2, hk, k, nk),
3365            h.gd_other(~K, ~V, ~eq, ~sound, p, (mask << 1n : U32), hi, h2, k2, hk, k, nk))
3366
3367
3368# size after put and del.
3369def h.split_size.b(
3370  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +p: Nat, +mask: U32, +o: U32,
3371  +es: List<&2, M.Entry<K, V>>, +hk: U32, +k: K, +v: V, b1: Bool, b2: Bool,
3372  ih: {h.Sz(K, V, h.S(~K, ~V, ~eq, p, (mask << 1n : U32), o, es, hk, k, v)) == 1n+h.len(K, V, es) : Nat}
3373) -> {h.Sz(K, V, h.sp(~K, ~V, ~eq, b1, b2, p, mask, o, es, hk, k, v)) == 1n+h.len(K, V, es) : Nat}:
3374  match b1 b2:
3375    case True{} True{}:
3376      Ord.tr(Nat.add(h.Sz(K, V, h.S(~K, ~V, ~eq, p, (mask << 1n : U32), o, es, hk, k, v)), 0n),
3377        h.Sz(K, V, h.S(~K, ~V, ~eq, p, (mask << 1n : U32), o, es, hk, k, v)), 1n+h.len(K, V, es),
3378        MNat.add_zero(h.Sz(K, V, h.S(~K, ~V, ~eq, p, (mask << 1n : U32), o, es, hk, k, v))), ih)
3379    case True{} False{}:
3380      ih
3381    case False{} True{}:
3382      Ord.tr(Nat.add(h.len(K, V, es), 1n), 1n+Nat.add(h.len(K, V, es), 0n), 1n+h.len(K, V, es),
3383        MNat.add_succ(h.len(K, V, es), 0n),
3384        Equal.cong(Nat, Nat, x => 1n+x, Nat.add(h.len(K, V, es), 0n), h.len(K, V, es),
3385          MNat.add_zero(h.len(K, V, es))))
3386    case False{} False{}:
3387      {==}
3388
3389def h.split_size(
3390  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, n: Nat, +mask: U32, +o: U32,
3391  +es: List<&2, M.Entry<K, V>>, +hk: U32, +k: K, +v: V,
3392  +miss: {h.EG(~K, ~V, ~eq, es, k) == None{} : Maybe<&2, V>}
3393) -> {h.Sz(K, V, h.S(~K, ~V, ~eq, n, mask, o, es, hk, k, v)) == 1n+h.len(K, V, es) : Nat}:
3394  match n:
3395    case 0n:
3396      h.elen_put_new(~K, ~V, ~eq, es, k, v, miss)
3397    case 1n+(+p):
3398      h.split_size.b(~K, ~V, ~eq, p, mask, o, es, hk, k, v,
3399        U32.is_eq((o .&. mask : U32), (hk .&. mask : U32)), U32.is_eq((o .&. mask : U32), 0),
3400        h.split_size(~K, ~V, ~eq, p, (mask << 1n : U32), o, es, hk, k, v, miss))
3401
3402def h.sz_put_new.lf(
3403  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool,
3404  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
3405  +p: Nat, +mask: U32, +o: U32, +es: List<&2, M.Entry<K, V>>, +k: K, +v: V,
3406  hs: {Laws.hmap_hashed(~K, ~V, ~hash, es, o) == True{} : Bool},
3407  b: Bool, eb: {b == U32.is_eq(o, hash(k)) : Bool},
3408  miss: {h.R(~K, ~V, ~hash, ~eq, o, es, k) == None{} : Maybe<&2, V>}
3409) -> {h.Sz(K, V, h.pl(~K, ~V, ~eq, b, p, mask, o, es, hash(k), k, v)) == 1n+h.len(K, V, es) : Nat}:
3410  match b:
3411    case True{}:
3412      h.elen_put_new(~K, ~V, ~eq, es, k, v,
3413        rw(Bool, z => {M.HMap.bool(Maybe<&2, V>, z, u => h.EG(~K, ~V, ~eq, es, k), u => None{}) == None{} : Maybe<&2, V>},
3414          True{}, U32.is_eq(o, hash(k)), eb, miss))
3415    case False{}:
3416      h.split_size(~K, ~V, ~eq, 1n+p, mask, o, es, hash(k), k, v,
3417        h.eg_none_hashed(~K, ~V, ~hash, ~eq, ~sound, es, o, k, h.sb(False{}, U32.is_eq(o, hash(k)), eb), hs))
3418
3419def h.sz_put_new.br(
3420  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +p: Nat, +mask: U32, +lo: M.HMap<K, V>,
3421  +hi: M.HMap<K, V>, +hk: U32, +k: K, +v: V, b: Bool, eb: {b == U32.is_eq((hk .&. mask : U32), 0) : Bool},
3422  miss: {M.HMap.bool(Maybe<&2, V>, U32.is_eq((hk .&. mask : U32), 0),
3423    u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k),
3424    u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)) == None{} : Maybe<&2, V>},
3425  il: {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k) == None{} : Maybe<&2, V>}
3426    -> {h.Sz(K, V, h.P(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k, v)) == 1n+h.Sz(K, V, lo) : Nat},
3427  ih: {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k) == None{} : Maybe<&2, V>}
3428    -> {h.Sz(K, V, h.P(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k, v)) == 1n+h.Sz(K, V, hi) : Nat}
3429) -> {h.Sz(K, V, h.pb(~K, ~V, ~eq, b, p, mask, lo, hi, hk, k, v))
3430      == 1n+Nat.add(h.Sz(K, V, lo), h.Sz(K, V, hi)) : Nat}:
3431  match b:
3432    case True{}:
3433      Ord.cong_add(h.Sz(K, V, h.P(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k, v)), 1n+h.Sz(K, V, lo),
3434        h.Sz(K, V, hi), h.Sz(K, V, hi),
3435        il(rw(Bool, z => {M.HMap.bool(Maybe<&2, V>, z,
3436            u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k),
3437            u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)) == None{} : Maybe<&2, V>},
3438          True{}, U32.is_eq((hk .&. mask : U32), 0), eb, miss)),
3439        {==})
3440    case False{}:
3441      Ord.tr(Nat.add(h.Sz(K, V, lo), h.Sz(K, V, h.P(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k, v))),
3442        Nat.add(h.Sz(K, V, lo), 1n+h.Sz(K, V, hi)), 1n+Nat.add(h.Sz(K, V, lo), h.Sz(K, V, hi)),
3443        Ord.cong_add(h.Sz(K, V, lo), h.Sz(K, V, lo),
3444          h.Sz(K, V, h.P(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k, v)), 1n+h.Sz(K, V, hi), {==},
3445          ih(rw(Bool, z => {M.HMap.bool(Maybe<&2, V>, z,
3446              u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k),
3447              u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)) == None{} : Maybe<&2, V>},
3448            False{}, U32.is_eq((hk .&. mask : U32), 0), eb, miss))),
3449        MNat.add_succ(h.Sz(K, V, lo), h.Sz(K, V, hi)))
3450
3451def h.sz_put_new(
3452  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool,
3453  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
3454  n: Nat, +mask: U32, m: M.HMap<K, V>, +k: K, +v: V,
3455  +wf: {h.WF(~K, ~V, ~hash, ~eq, n, m) == True{} : Bool},
3456  miss: {h.G(~K, ~V, ~eq, n, mask, m, hash(k), k) == None{} : Maybe<&2, V>}
3457) -> {h.Sz(K, V, h.P(~K, ~V, ~eq, n, mask, m, hash(k), k, v)) == 1n+h.Sz(K, V, m) : Nat}:
3458  match n:
3459    case 0n:
3460      match m:
3461        case M.HNil{}:
3462          {==}
3463        case M.HLeaf{o, es}:
3464          h.elen_put_new(~K, ~V, ~eq, es, k, v, miss)
3465        case M.HBranch{lo, hi}:
3466          Empty.absurd({h.Sz(K, V, M.HBranch{lo, hi}) == 1n+h.Sz(K, V, M.HBranch{lo, hi}) : Nat}, MBool.false_ne_true()(wf))
3467    case 1n+(+p):
3468      match m:
3469        case M.HNil{}:
3470          {==}
3471        case M.HLeaf{+o, +es}:
3472          h.sz_put_new.lf(~K, ~V, ~hash, ~eq, ~sound, p, mask, o, es, k, v,
3473            MBool.eq_true_of_and_left(Laws.hmap_hashed(~K, ~V, ~hash, es, o), Laws.hmap_distinct(~K, ~V, ~eq, es), wf),
3474            U32.is_eq(o, hash(k)), {==}, miss)
3475        case M.HBranch{+lo, +hi}:
3476          h.sz_put_new.br(~K, ~V, ~eq, p, mask, lo, hi, hash(k), k, v, U32.is_eq((hash(k) .&. mask : U32), 0), {==},
3477            miss,
3478            e => h.sz_put_new(~K, ~V, ~hash, ~eq, ~sound, p, (mask << 1n : U32), lo, k, v,
3479              MBool.eq_true_of_and_left(h.WF(~K, ~V, ~hash, ~eq, p, lo), h.WF(~K, ~V, ~hash, ~eq, p, hi), wf), e),
3480            e => h.sz_put_new(~K, ~V, ~hash, ~eq, ~sound, p, (mask << 1n : U32), hi, k, v,
3481              MBool.eq_true_of_and_right(h.WF(~K, ~V, ~hash, ~eq, p, lo), h.WF(~K, ~V, ~hash, ~eq, p, hi), wf), e))
3482
3483def h.sz_put_hit.lf(
3484  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +p: Nat, +mask: U32, +o: U32,
3485  +es: List<&2, M.Entry<K, V>>, +hk: U32, +k: K, +v: V, -w: V,
3486  b: Bool, eb: {b == U32.is_eq(o, hk) : Bool},
3487  hit: {M.HMap.bool(Maybe<&2, V>, U32.is_eq(o, hk), u => h.EG(~K, ~V, ~eq, es, k), u => None{}) == Some{w} : Maybe<&2, V>}
3488) -> {h.Sz(K, V, h.pl(~K, ~V, ~eq, b, p, mask, o, es, hk, k, v)) == h.len(K, V, es) : Nat}:
3489  match b:
3490    case True{}:
3491      h.elen_put_hit(~K, ~V, ~eq, es, k, v, w,
3492        rw(Bool, z => {M.HMap.bool(Maybe<&2, V>, z, u => h.EG(~K, ~V, ~eq, es, k), u => None{}) == Some{w} : Maybe<&2, V>},
3493          True{}, U32.is_eq(o, hk), eb, hit))
3494    case False{}:
3495      h.none_some({h.Sz(K, V, h.S(~K, ~V, ~eq, 1n+p, mask, o, es, hk, k, v)) == h.len(K, V, es) : Nat}, V, w,
3496        rw(Bool, z => {M.HMap.bool(Maybe<&2, V>, z, u => h.EG(~K, ~V, ~eq, es, k), u => None{}) == Some{w} : Maybe<&2, V>},
3497          False{}, U32.is_eq(o, hk), eb, hit))
3498
3499def h.sz_put_hit.br(
3500  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +p: Nat, +mask: U32, +lo: M.HMap<K, V>,
3501  +hi: M.HMap<K, V>, +hk: U32, +k: K, +v: V, -w: V, b: Bool, eb: {b == U32.is_eq((hk .&. mask : U32), 0) : Bool},
3502  hit: {M.HMap.bool(Maybe<&2, V>, U32.is_eq((hk .&. mask : U32), 0),
3503    u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k),
3504    u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)) == Some{w} : Maybe<&2, V>},
3505  il: {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k) == Some{w} : Maybe<&2, V>}
3506    -> {h.Sz(K, V, h.P(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k, v)) == h.Sz(K, V, lo) : Nat},
3507  ih: {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k) == Some{w} : Maybe<&2, V>}
3508    -> {h.Sz(K, V, h.P(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k, v)) == h.Sz(K, V, hi) : Nat}
3509) -> {h.Sz(K, V, h.pb(~K, ~V, ~eq, b, p, mask, lo, hi, hk, k, v))
3510      == Nat.add(h.Sz(K, V, lo), h.Sz(K, V, hi)) : Nat}:
3511  match b:
3512    case True{}:
3513      Ord.cong_add(h.Sz(K, V, h.P(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k, v)), h.Sz(K, V, lo),
3514        h.Sz(K, V, hi), h.Sz(K, V, hi),
3515        il(rw(Bool, z => {M.HMap.bool(Maybe<&2, V>, z,
3516            u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k),
3517            u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)) == Some{w} : Maybe<&2, V>},
3518          True{}, U32.is_eq((hk .&. mask : U32), 0), eb, hit)),
3519        {==})
3520    case False{}:
3521      Ord.cong_add(h.Sz(K, V, lo), h.Sz(K, V, lo),
3522        h.Sz(K, V, h.P(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k, v)), h.Sz(K, V, hi), {==},
3523        ih(rw(Bool, z => {M.HMap.bool(Maybe<&2, V>, z,
3524            u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k),
3525            u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)) == Some{w} : Maybe<&2, V>},
3526          False{}, U32.is_eq((hk .&. mask : U32), 0), eb, hit)))
3527
3528def h.sz_put_hit(
3529  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, n: Nat, +mask: U32, m: M.HMap<K, V>, +hk: U32, +k: K, +v: V, -w: V,
3530  hit: {h.G(~K, ~V, ~eq, n, mask, m, hk, k) == Some{w} : Maybe<&2, V>}
3531) -> {h.Sz(K, V, h.P(~K, ~V, ~eq, n, mask, m, hk, k, v)) == h.Sz(K, V, m) : Nat}:
3532  match n:
3533    case 0n:
3534      match m:
3535        case M.HNil{}:
3536          h.none_some({h.Sz(K, V, M.HLeaf{hk, [M.Entry{k, v}]}) == 0n : Nat}, V, w, hit)
3537        case M.HLeaf{o, es}:
3538          h.elen_put_hit(~K, ~V, ~eq, es, k, v, w, hit)
3539        case M.HBranch{lo, hi}:
3540          {==}
3541    case 1n+(+p):
3542      match m:
3543        case M.HNil{}:
3544          h.none_some({h.Sz(K, V, M.HLeaf{hk, [M.Entry{k, v}]}) == 0n : Nat}, V, w, hit)
3545        case M.HLeaf{+o, +es}:
3546          h.sz_put_hit.lf(~K, ~V, ~eq, p, mask, o, es, hk, k, v, w, U32.is_eq(o, hk), {==}, hit)
3547        case M.HBranch{+lo, +hi}:
3548          h.sz_put_hit.br(~K, ~V, ~eq, p, mask, lo, hi, hk, k, v, w, U32.is_eq((hk .&. mask : U32), 0), {==}, hit,
3549            e => h.sz_put_hit(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k, v, w, e),
3550            e => h.sz_put_hit(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k, v, w, e))
3551
3552def h.sz_del_hit.lf(
3553  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +o: U32,
3554  +es: List<&2, M.Entry<K, V>>, +hk: U32, +k: K, -w: V,
3555  b: Bool, eb: {b == U32.is_eq(o, hk) : Bool},
3556  hit: {M.HMap.bool(Maybe<&2, V>, U32.is_eq(o, hk), u => h.EG(~K, ~V, ~eq, es, k), u => None{}) == Some{w} : Maybe<&2, V>}
3557) -> {1n+h.Sz(K, V, h.dl(~K, ~V, ~eq, b, o, es, k)) == h.len(K, V, es) : Nat}:
3558  match b:
3559    case True{}:
3560      %h.size_leaf(K, V, o, M.HMap.entries.del(~K, ~V, ~eq, es, k)) : {1n+_ == h.len(K, V, es) : Nat}
3561      h.elen_del_hit(~K, ~V, ~eq, es, k, w,
3562        rw(Bool, z => {M.HMap.bool(Maybe<&2, V>, z, u => h.EG(~K, ~V, ~eq, es, k), u => None{}) == Some{w} : Maybe<&2, V>},
3563          True{}, U32.is_eq(o, hk), eb, hit))
3564    case False{}:
3565      h.none_some({1n+h.len(K, V, es) == h.len(K, V, es) : Nat}, V, w,
3566        rw(Bool, z => {M.HMap.bool(Maybe<&2, V>, z, u => h.EG(~K, ~V, ~eq, es, k), u => None{}) == Some{w} : Maybe<&2, V>},
3567          False{}, U32.is_eq(o, hk), eb, hit))
3568
3569def h.sz_del_hit.br(
3570  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +p: Nat, +mask: U32, +lo: M.HMap<K, V>,
3571  +hi: M.HMap<K, V>, +hk: U32, +k: K, -w: V, b: Bool, eb: {b == U32.is_eq((hk .&. mask : U32), 0) : Bool},
3572  hit: {M.HMap.bool(Maybe<&2, V>, U32.is_eq((hk .&. mask : U32), 0),
3573    u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k),
3574    u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)) == Some{w} : Maybe<&2, V>},
3575  il: {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k) == Some{w} : Maybe<&2, V>}
3576    -> {1n+h.Sz(K, V, h.D(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k)) == h.Sz(K, V, lo) : Nat},
3577  ih: {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k) == Some{w} : Maybe<&2, V>}
3578    -> {1n+h.Sz(K, V, h.D(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)) == h.Sz(K, V, hi) : Nat}
3579) -> {1n+h.Sz(K, V, h.db(~K, ~V, ~eq, b, p, mask, lo, hi, hk, k))
3580      == Nat.add(h.Sz(K, V, lo), h.Sz(K, V, hi)) : Nat}:
3581  match b:
3582    case True{}:
3583      +dlo = h.D(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k)
3584      %h.size_join(K, V, dlo, hi) : {1n+_ == Nat.add(h.Sz(K, V, lo), h.Sz(K, V, hi)) : Nat}
3585      Ord.cong_add(1n+h.Sz(K, V, dlo), h.Sz(K, V, lo), h.Sz(K, V, hi), h.Sz(K, V, hi),
3586        il(rw(Bool, z => {M.HMap.bool(Maybe<&2, V>, z,
3587            u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k),
3588            u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)) == Some{w} : Maybe<&2, V>},
3589          True{}, U32.is_eq((hk .&. mask : U32), 0), eb, hit)),
3590        {==})
3591    case False{}:
3592      +dhi = h.D(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)
3593      %h.size_join(K, V, lo, dhi) : {1n+_ == Nat.add(h.Sz(K, V, lo), h.Sz(K, V, hi)) : Nat}
3594      %MNat.add_succ(h.Sz(K, V, lo), h.Sz(K, V, dhi)) : {_ == Nat.add(h.Sz(K, V, lo), h.Sz(K, V, hi)) : Nat}
3595      Ord.cong_add(h.Sz(K, V, lo), h.Sz(K, V, lo), 1n+h.Sz(K, V, dhi), h.Sz(K, V, hi), {==},
3596        ih(rw(Bool, z => {M.HMap.bool(Maybe<&2, V>, z,
3597            u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k),
3598            u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)) == Some{w} : Maybe<&2, V>},
3599          False{}, U32.is_eq((hk .&. mask : U32), 0), eb, hit)))
3600
3601def h.sz_del_hit(
3602  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, n: Nat, +mask: U32, m: M.HMap<K, V>, +hk: U32, +k: K, -w: V,
3603  hit: {h.G(~K, ~V, ~eq, n, mask, m, hk, k) == Some{w} : Maybe<&2, V>}
3604) -> {1n+h.Sz(K, V, h.D(~K, ~V, ~eq, n, mask, m, hk, k)) == h.Sz(K, V, m) : Nat}:
3605  match n:
3606    case 0n:
3607      match m:
3608        case M.HNil{}:
3609          h.none_some({1n == 0n : Nat}, V, w, hit)
3610        case M.HLeaf{+o, +es}:
3611          %h.size_leaf(K, V, o, M.HMap.entries.del(~K, ~V, ~eq, es, k)) : {1n+_ == h.len(K, V, es) : Nat}
3612          h.elen_del_hit(~K, ~V, ~eq, es, k, w, hit)
3613        case M.HBranch{+lo, +hi}:
3614          h.none_some({1n+h.Sz(K, V, M.HBranch{lo, hi}) == h.Sz(K, V, M.HBranch{lo, hi}) : Nat}, V, w, hit)
3615    case 1n+(+p):
3616      match m:
3617        case M.HNil{}:
3618          h.none_some({1n == 0n : Nat}, V, w, hit)
3619        case M.HLeaf{+o, +es}:
3620          h.sz_del_hit.lf(~K, ~V, ~eq, o, es, hk, k, w, U32.is_eq(o, hk), {==}, hit)
3621        case M.HBranch{+lo, +hi}:
3622          h.sz_del_hit.br(~K, ~V, ~eq, p, mask, lo, hi, hk, k, w, U32.is_eq((hk .&. mask : U32), 0), {==}, hit,
3623            e => h.sz_del_hit(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k, w, e),
3624            e => h.sz_del_hit(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k, w, e))
3625
3626def h.sz_del_miss.lf(
3627  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +o: U32,
3628  +es: List<&2, M.Entry<K, V>>, +hk: U32, +k: K,
3629  b: Bool, eb: {b == U32.is_eq(o, hk) : Bool},
3630  miss: {M.HMap.bool(Maybe<&2, V>, U32.is_eq(o, hk), u => h.EG(~K, ~V, ~eq, es, k), u => None{}) == None{} : Maybe<&2, V>}
3631) -> {h.Sz(K, V, h.dl(~K, ~V, ~eq, b, o, es, k)) == h.len(K, V, es) : Nat}:
3632  match b:
3633    case True{}:
3634      %h.size_leaf(K, V, o, M.HMap.entries.del(~K, ~V, ~eq, es, k)) : {_ == h.len(K, V, es) : Nat}
3635      Equal.cong(List<&2, M.Entry<K, V>>, Nat, xs => h.len(K, V, xs), M.HMap.entries.del(~K, ~V, ~eq, es, k), es,
3636        h.edel_miss(~K, ~V, ~eq, es, k,
3637          rw(Bool, z => {M.HMap.bool(Maybe<&2, V>, z, u => h.EG(~K, ~V, ~eq, es, k), u => None{}) == None{} : Maybe<&2, V>},
3638            True{}, U32.is_eq(o, hk), eb, miss)))
3639    case False{}:
3640      {==}
3641
3642def h.sz_del_miss.br(
3643  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, +p: Nat, +mask: U32, +lo: M.HMap<K, V>,
3644  +hi: M.HMap<K, V>, +hk: U32, +k: K, b: Bool, eb: {b == U32.is_eq((hk .&. mask : U32), 0) : Bool},
3645  miss: {M.HMap.bool(Maybe<&2, V>, U32.is_eq((hk .&. mask : U32), 0),
3646    u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k),
3647    u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)) == None{} : Maybe<&2, V>},
3648  il: {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k) == None{} : Maybe<&2, V>}
3649    -> {h.Sz(K, V, h.D(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k)) == h.Sz(K, V, lo) : Nat},
3650  ih: {h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k) == None{} : Maybe<&2, V>}
3651    -> {h.Sz(K, V, h.D(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)) == h.Sz(K, V, hi) : Nat}
3652) -> {h.Sz(K, V, h.db(~K, ~V, ~eq, b, p, mask, lo, hi, hk, k))
3653      == Nat.add(h.Sz(K, V, lo), h.Sz(K, V, hi)) : Nat}:
3654  match b:
3655    case True{}:
3656      +dlo = h.D(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k)
3657      %h.size_join(K, V, dlo, hi) : {_ == Nat.add(h.Sz(K, V, lo), h.Sz(K, V, hi)) : Nat}
3658      Ord.cong_add(h.Sz(K, V, dlo), h.Sz(K, V, lo), h.Sz(K, V, hi), h.Sz(K, V, hi),
3659        il(rw(Bool, z => {M.HMap.bool(Maybe<&2, V>, z,
3660            u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k),
3661            u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)) == None{} : Maybe<&2, V>},
3662          True{}, U32.is_eq((hk .&. mask : U32), 0), eb, miss)),
3663        {==})
3664    case False{}:
3665      +dhi = h.D(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)
3666      %h.size_join(K, V, lo, dhi) : {_ == Nat.add(h.Sz(K, V, lo), h.Sz(K, V, hi)) : Nat}
3667      Ord.cong_add(h.Sz(K, V, lo), h.Sz(K, V, lo), h.Sz(K, V, dhi), h.Sz(K, V, hi), {==},
3668        ih(rw(Bool, z => {M.HMap.bool(Maybe<&2, V>, z,
3669            u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k),
3670            u => h.G(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)) == None{} : Maybe<&2, V>},
3671          False{}, U32.is_eq((hk .&. mask : U32), 0), eb, miss)))
3672
3673def h.sz_del_miss(
3674  ~K: Data, ~V: Data, ~eq: K -> K -> Bool, n: Nat, +mask: U32, m: M.HMap<K, V>, +hk: U32, +k: K,
3675  miss: {h.G(~K, ~V, ~eq, n, mask, m, hk, k) == None{} : Maybe<&2, V>}
3676) -> {h.Sz(K, V, h.D(~K, ~V, ~eq, n, mask, m, hk, k)) == h.Sz(K, V, m) : Nat}:
3677  match n:
3678    case 0n:
3679      match m:
3680        case M.HNil{}:
3681          {==}
3682        case M.HLeaf{+o, +es}:
3683          %h.size_leaf(K, V, o, M.HMap.entries.del(~K, ~V, ~eq, es, k)) : {_ == h.len(K, V, es) : Nat}
3684          Equal.cong(List<&2, M.Entry<K, V>>, Nat, xs => h.len(K, V, xs), M.HMap.entries.del(~K, ~V, ~eq, es, k), es,
3685            h.edel_miss(~K, ~V, ~eq, es, k, miss))
3686        case M.HBranch{lo, hi}:
3687          {==}
3688    case 1n+(+p):
3689      match m:
3690        case M.HNil{}:
3691          {==}
3692        case M.HLeaf{+o, +es}:
3693          h.sz_del_miss.lf(~K, ~V, ~eq, o, es, hk, k, U32.is_eq(o, hk), {==}, miss)
3694        case M.HBranch{+lo, +hi}:
3695          h.sz_del_miss.br(~K, ~V, ~eq, p, mask, lo, hi, hk, k, U32.is_eq((hk .&. mask : U32), 0), {==}, miss,
3696            e => h.sz_del_miss(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k, e),
3697            e => h.sz_del_miss(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k, e))
3698
3699# put and del keep the map well formed.
3700def h.wf_fresh(~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool, p: Nat, +k: K, +v: V)
3701  -> {h.WF(~K, ~V, ~hash, ~eq, p, M.HLeaf{hash(k), [M.Entry{k, v}]}) == True{} : Bool}:
3702  match p:
3703    case 0n:
3704      {==}
3705    case 1n+q:
3706      %h.sb(U32.is_eq(hash(k), hash(k)), True{}, h.u_refl(hash(k)))
3707        : {Bool.and(Bool.and(_, True{}), True{}) == True{} : Bool}
3708      {==}
3709
3710def h.wf_leaf_o(
3711  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool, p: Nat, +o: U32,
3712  +es: List<&2, M.Entry<K, V>>,
3713  hs: {Laws.hmap_hashed(~K, ~V, ~hash, es, o) == True{} : Bool},
3714  ds: {Laws.hmap_distinct(~K, ~V, ~eq, es) == True{} : Bool}
3715) -> {h.WF(~K, ~V, ~hash, ~eq, p, M.HLeaf{o, es}) == True{} : Bool}:
3716  match p:
3717    case 0n:
3718      ds
3719    case 1n+q:
3720      MBool.and_eq_true(Laws.hmap_hashed(~K, ~V, ~hash, es, o), Laws.hmap_distinct(~K, ~V, ~eq, es), hs, ds)
3721
3722def h.split_wf.b(
3723  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool, +p: Nat, +mask: U32, +o: U32,
3724  +es: List<&2, M.Entry<K, V>>, +k: K, +v: V,
3725  +hs: {Laws.hmap_hashed(~K, ~V, ~hash, es, o) == True{} : Bool},
3726  +ds: {Laws.hmap_distinct(~K, ~V, ~eq, es) == True{} : Bool},
3727  b1: Bool, b2: Bool,
3728  ih: {h.WF(~K, ~V, ~hash, ~eq, p, h.S(~K, ~V, ~eq, p, (mask << 1n : U32), o, es, hash(k), k, v)) == True{} : Bool}
3729) -> {h.WF(~K, ~V, ~hash, ~eq, 1n+p, h.sp(~K, ~V, ~eq, b1, b2, p, mask, o, es, hash(k), k, v)) == True{} : Bool}:
3730  match b1 b2:
3731    case True{} True{}:
3732      MBool.and_eq_true(h.WF(~K, ~V, ~hash, ~eq, p, h.S(~K, ~V, ~eq, p, (mask << 1n : U32), o, es, hash(k), k, v)), h.WF(~K, ~V, ~hash, ~eq, p, M.HNil{}), ih, h.wf_nil(~K, ~V, ~hash, ~eq, p))
3733    case True{} False{}:
3734      MBool.and_eq_true(h.WF(~K, ~V, ~hash, ~eq, p, M.HNil{}), h.WF(~K, ~V, ~hash, ~eq, p, h.S(~K, ~V, ~eq, p, (mask << 1n : U32), o, es, hash(k), k, v)), h.wf_nil(~K, ~V, ~hash, ~eq, p), ih)
3735    case False{} True{}:
3736      MBool.and_eq_true(h.WF(~K, ~V, ~hash, ~eq, p, M.HLeaf{o, es}), h.WF(~K, ~V, ~hash, ~eq, p, M.HLeaf{hash(k), [M.Entry{k, v}]}), h.wf_leaf_o(~K, ~V, ~hash, ~eq, p, o, es, hs, ds), h.wf_fresh(~K, ~V, ~hash, ~eq, p, k, v))
3737    case False{} False{}:
3738      MBool.and_eq_true(h.WF(~K, ~V, ~hash, ~eq, p, M.HLeaf{hash(k), [M.Entry{k, v}]}), h.WF(~K, ~V, ~hash, ~eq, p, M.HLeaf{o, es}), h.wf_fresh(~K, ~V, ~hash, ~eq, p, k, v), h.wf_leaf_o(~K, ~V, ~hash, ~eq, p, o, es, hs, ds))
3739
3740def h.split_wf(
3741  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool, ~refl: @x: K -> {eq(x, x) == True{} : Bool},
3742  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
3743  n: Nat, +mask: U32, +o: U32, +es: List<&2, M.Entry<K, V>>, +k: K, +v: V,
3744  +hs: {Laws.hmap_hashed(~K, ~V, ~hash, es, o) == True{} : Bool},
3745  +ds: {Laws.hmap_distinct(~K, ~V, ~eq, es) == True{} : Bool}
3746) -> {h.WF(~K, ~V, ~hash, ~eq, n, h.S(~K, ~V, ~eq, n, mask, o, es, hash(k), k, v)) == True{} : Bool}:
3747  match n:
3748    case 0n:
3749      h.distinct_put(~K, ~V, ~eq, ~refl, ~sound, es, k, v, ds)
3750    case 1n+(+p):
3751      h.split_wf.b(~K, ~V, ~hash, ~eq, p, mask, o, es, k, v, hs, ds,
3752        U32.is_eq((o .&. mask : U32), (hash(k) .&. mask : U32)), U32.is_eq((o .&. mask : U32), 0),
3753        h.split_wf(~K, ~V, ~hash, ~eq, ~refl, ~sound, p, (mask << 1n : U32), o, es, k, v, hs, ds))
3754
3755def h.wf_put.lf(
3756  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool, ~refl: @x: K -> {eq(x, x) == True{} : Bool},
3757  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
3758  +p: Nat, +mask: U32, +o: U32, +es: List<&2, M.Entry<K, V>>, +k: K, +v: V,
3759  hs: {Laws.hmap_hashed(~K, ~V, ~hash, es, o) == True{} : Bool},
3760  ds: {Laws.hmap_distinct(~K, ~V, ~eq, es) == True{} : Bool},
3761  b: Bool, eb: {b == U32.is_eq(o, hash(k)) : Bool},
3762  sp: {h.WF(~K, ~V, ~hash, ~eq, 1n+p, h.S(~K, ~V, ~eq, 1n+p, mask, o, es, hash(k), k, v)) == True{} : Bool}
3763) -> {h.WF(~K, ~V, ~hash, ~eq, 1n+p, h.pl(~K, ~V, ~eq, b, p, mask, o, es, hash(k), k, v)) == True{} : Bool}:
3764  match b:
3765    case True{}:
3766      MBool.and_eq_true(Laws.hmap_hashed(~K, ~V, ~hash, M.HMap.entries.put(~K, ~V, ~eq, es, k, v), o), Laws.hmap_distinct(~K, ~V, ~eq, M.HMap.entries.put(~K, ~V, ~eq, es, k, v)), h.hashed_put(~K, ~V, ~hash, ~eq, es, o, k, v, h.sb(True{}, U32.is_eq(o, hash(k)), eb), hs), h.distinct_put(~K, ~V, ~eq, ~refl, ~sound, es, k, v, ds))
3767    case False{}:
3768      sp
3769
3770def h.wf_put.br(
3771  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool, +p: Nat, +mask: U32, +lo: M.HMap<K, V>,
3772  +hi: M.HMap<K, V>, +hk: U32, +k: K, +v: V, b: Bool,
3773  wl: {h.WF(~K, ~V, ~hash, ~eq, p, lo) == True{} : Bool},
3774  wh: {h.WF(~K, ~V, ~hash, ~eq, p, hi) == True{} : Bool},
3775  il: {h.WF(~K, ~V, ~hash, ~eq, p, h.P(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k, v)) == True{} : Bool},
3776  ih: {h.WF(~K, ~V, ~hash, ~eq, p, h.P(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k, v)) == True{} : Bool}
3777) -> {h.WF(~K, ~V, ~hash, ~eq, 1n+p, h.pb(~K, ~V, ~eq, b, p, mask, lo, hi, hk, k, v)) == True{} : Bool}:
3778  match b:
3779    case True{}:
3780      MBool.and_eq_true(h.WF(~K, ~V, ~hash, ~eq, p, h.P(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k, v)), h.WF(~K, ~V, ~hash, ~eq, p, hi), il, wh)
3781    case False{}:
3782      MBool.and_eq_true(h.WF(~K, ~V, ~hash, ~eq, p, lo), h.WF(~K, ~V, ~hash, ~eq, p, h.P(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k, v)), wl, ih)
3783
3784def h.wf_put(
3785  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool, ~refl: @x: K -> {eq(x, x) == True{} : Bool},
3786  ~sound: @x: K -> @y: K -> {eq(x, y) == True{} : Bool} -> {x == y : K},
3787  n: Nat, +mask: U32, m: M.HMap<K, V>, +k: K, +v: V,
3788  +wf: {h.WF(~K, ~V, ~hash, ~eq, n, m) == True{} : Bool}
3789) -> {h.WF(~K, ~V, ~hash, ~eq, n, h.P(~K, ~V, ~eq, n, mask, m, hash(k), k, v)) == True{} : Bool}:
3790  match n:
3791    case 0n:
3792      match m:
3793        case M.HNil{}:
3794          {==}
3795        case M.HLeaf{o, es}:
3796          h.distinct_put(~K, ~V, ~eq, ~refl, ~sound, es, k, v, wf)
3797        case M.HBranch{lo, hi}:
3798          wf
3799    case 1n+(+p):
3800      match m:
3801        case M.HNil{}:
3802          h.wf_fresh(~K, ~V, ~hash, ~eq, 1n+p, k, v)
3803        case M.HLeaf{+o, +es}:
3804          h.wf_put.lf(~K, ~V, ~hash, ~eq, ~refl, ~sound, p, mask, o, es, k, v,
3805            MBool.eq_true_of_and_left(Laws.hmap_hashed(~K, ~V, ~hash, es, o), Laws.hmap_distinct(~K, ~V, ~eq, es), wf),
3806            MBool.eq_true_of_and_right(Laws.hmap_hashed(~K, ~V, ~hash, es, o), Laws.hmap_distinct(~K, ~V, ~eq, es), wf),
3807            U32.is_eq(o, hash(k)), {==},
3808            h.split_wf(~K, ~V, ~hash, ~eq, ~refl, ~sound, 1n+p, mask, o, es, k, v,
3809              MBool.eq_true_of_and_left(Laws.hmap_hashed(~K, ~V, ~hash, es, o), Laws.hmap_distinct(~K, ~V, ~eq, es), wf),
3810              MBool.eq_true_of_and_right(Laws.hmap_hashed(~K, ~V, ~hash, es, o), Laws.hmap_distinct(~K, ~V, ~eq, es), wf)))
3811        case M.HBranch{+lo, +hi}:
3812          h.wf_put.br(~K, ~V, ~hash, ~eq, p, mask, lo, hi, hash(k), k, v, U32.is_eq((hash(k) .&. mask : U32), 0),
3813            MBool.eq_true_of_and_left(h.WF(~K, ~V, ~hash, ~eq, p, lo), h.WF(~K, ~V, ~hash, ~eq, p, hi), wf),
3814            MBool.eq_true_of_and_right(h.WF(~K, ~V, ~hash, ~eq, p, lo), h.WF(~K, ~V, ~hash, ~eq, p, hi), wf),
3815            h.wf_put(~K, ~V, ~hash, ~eq, ~refl, ~sound, p, (mask << 1n : U32), lo, k, v,
3816              MBool.eq_true_of_and_left(h.WF(~K, ~V, ~hash, ~eq, p, lo), h.WF(~K, ~V, ~hash, ~eq, p, hi), wf)),
3817            h.wf_put(~K, ~V, ~hash, ~eq, ~refl, ~sound, p, (mask << 1n : U32), hi, k, v,
3818              MBool.eq_true_of_and_right(h.WF(~K, ~V, ~hash, ~eq, p, lo), h.WF(~K, ~V, ~hash, ~eq, p, hi), wf)))
3819
3820def h.wf_del.lf(
3821  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool, +p: Nat, +o: U32,
3822  +es: List<&2, M.Entry<K, V>>, +k: K,
3823  +hs: {Laws.hmap_hashed(~K, ~V, ~hash, es, o) == True{} : Bool},
3824  +ds: {Laws.hmap_distinct(~K, ~V, ~eq, es) == True{} : Bool}, b: Bool
3825) -> {h.WF(~K, ~V, ~hash, ~eq, 1n+p, h.dl(~K, ~V, ~eq, b, o, es, k)) == True{} : Bool}:
3826  match b:
3827    case True{}:
3828      h.wf_leaf(~K, ~V, ~hash, ~eq, 1n+p, o, M.HMap.entries.del(~K, ~V, ~eq, es, k),
3829        MBool.and_eq_true(Laws.hmap_hashed(~K, ~V, ~hash, M.HMap.entries.del(~K, ~V, ~eq, es, k), o), Laws.hmap_distinct(~K, ~V, ~eq, M.HMap.entries.del(~K, ~V, ~eq, es, k)), h.hashed_del(~K, ~V, ~hash, ~eq, es, o, k, hs), h.distinct_del(~K, ~V, ~eq, es, k, ds)))
3830    case False{}:
3831      MBool.and_eq_true(Laws.hmap_hashed(~K, ~V, ~hash, es, o), Laws.hmap_distinct(~K, ~V, ~eq, es), hs, ds)
3832
3833def h.wf_del.br(
3834  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool, +p: Nat, +mask: U32, +lo: M.HMap<K, V>,
3835  +hi: M.HMap<K, V>, +hk: U32, +k: K, b: Bool,
3836  wl: {h.WF(~K, ~V, ~hash, ~eq, p, lo) == True{} : Bool},
3837  wh: {h.WF(~K, ~V, ~hash, ~eq, p, hi) == True{} : Bool},
3838  il: {h.WF(~K, ~V, ~hash, ~eq, p, h.D(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k)) == True{} : Bool},
3839  ih: {h.WF(~K, ~V, ~hash, ~eq, p, h.D(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k)) == True{} : Bool}
3840) -> {h.WF(~K, ~V, ~hash, ~eq, 1n+p, h.db(~K, ~V, ~eq, b, p, mask, lo, hi, hk, k)) == True{} : Bool}:
3841  match b:
3842    case True{}:
3843      h.wf_join(~K, ~V, ~hash, ~eq, p, h.D(~K, ~V, ~eq, p, (mask << 1n : U32), lo, hk, k), hi, il, wh)
3844    case False{}:
3845      h.wf_join(~K, ~V, ~hash, ~eq, p, lo, h.D(~K, ~V, ~eq, p, (mask << 1n : U32), hi, hk, k), wl, ih)
3846
3847def h.wf_del(
3848  ~K: Data, ~V: Data, ~hash: K -> U32, ~eq: K -> K -> Bool,
3849  n: Nat, +mask: U32, m: M.HMap<K, V>, +hk: U32, +k: K,
3850  +wf: {h.WF(~K, ~V, ~hash, ~eq, n, m) == True{} : Bool}
3851) -> {h.WF(~K, ~V, ~hash, ~eq, n, h.D(~K, ~V, ~eq, n, mask, m, hk, k)) == True{} : Bool}:
3852  match n:
3853    case 0n:
3854      match m:
3855        case M.HNil{}:
3856          {==}
3857        case M.HLeaf{+o, +es}:
3858          h.wf_leaf(~K, ~V, ~hash, ~eq, 0n, o, M.HMap.entries.del(~K, ~V, ~eq, es, k),
3859            h.distinct_del(~K, ~V, ~eq, es, k, wf))
3860        case M.HBranch{lo, hi}:
3861          wf
3862    case 1n+(+p):
3863      match m:
3864        case M.HNil{}:
3865          {==}
3866        case M.HLeaf{+o, +es}:
3867          h.wf_del.lf(~K, ~V, ~hash, ~eq, p, o, es, k,
3868            MBool.eq_true_of_and_left(Laws.hmap_hashed(~K, ~V, ~hash, es, o), Laws.hmap_distinct(~K, ~V, ~eq, es), wf),
3869            MBool.eq_true_of_and_right(Laws.hmap_hashed(~K, ~V, ~hash, es, o), Laws.hmap_distinct(~K, ~V, ~eq, es), wf),
3870            U32.is_eq(o, hk))
3871        case M.HBranch{+lo, +hi}:
3872          h.wf_del.br(~K, ~V, ~hash, ~eq, p, mask, lo, hi, hk, k, U32.is_eq((hk .&. mask : U32), 0),
3873            MBool.eq_true_of_and_left(h.WF(~K, ~V, ~hash, ~eq, p, lo), h.WF(~K, ~V, ~hash, ~eq, p, hi), wf),
3874            MBool.eq_true_of_and_right(h.WF(~K, ~V, ~hash, ~eq, p, lo), h.WF(~K, ~V, ~hash, ~eq, p, hi), wf),
3875            h.wf_del(~K, ~V, ~hash, ~eq, p, (mask << 1n : U32), lo, hk, k,
3876              MBool.eq_true_of_and_left(h.WF(~K, ~V, ~hash, ~eq, p, lo), h.WF(~K, ~V, ~hash, ~eq, p, hi), wf)),
3877            h.wf_del(~K, ~V, ~hash, ~eq, p, (mask << 1n : U32), hi, hk, k,
3878              MBool.eq_true_of_and_right(h.WF(~K, ~V, ~hash, ~eq, p, lo), h.WF(~K, ~V, ~hash, ~eq, p, hi), wf)))
3879
3880# --- hmap laws -------------------------------------------------------------------
3881
3882def Laws.hmap_new_wf(K, V, hash, eq):
3883  {==}
3884
3885def Laws.hmap_put_wf(K, V, hash, eq, refl, sound, m, wf, k, v):
3886  h.wf_put(~K, ~V, ~hash, ~eq, ~refl, ~sound, 32n, 1, m, k, v, wf)
3887
3888def Laws.hmap_del_wf(K, V, hash, eq, m, wf, k):
3889  h.wf_del(~K, ~V, ~hash, ~eq, 32n, 1, m, hash(k), k, wf)
3890
3891def Laws.hmap_get_put_same(K, V, hash, eq, refl, m, wf, k, v):
3892  h.gp_same(~K, ~V, ~hash, ~eq, ~refl, 32n, 1, m, hash(k), k, v, {==}, wf)
3893
3894def Laws.hmap_get_put_other_key(K, V, hash, eq, sound, m, wf, k2, k, ne, v):
3895  h.gp_other(~K, ~V, ~hash, ~eq, ~sound, 32n, 1, m, hash(k2), k2, k, v, wf,
3896    h.ne_f(~K, ~eq, ~sound, k2, k, ne))
3897
3898def Laws.hmap_get_del_same(K, V, hash, eq, sound, m, wf, k):
3899  h.gd_same(~K, ~V, ~hash, ~eq, ~sound, 32n, 1, m, hash(k), k, wf)
3900
3901def Laws.hmap_get_del_other_key(K, V, hash, eq, sound, m, k2, k, ne):
3902  h.gd_other(~K, ~V, ~eq, ~sound, 32n, 1, m, hash(k2), k2, hash(k), k, h.ne_f(~K, ~eq, ~sound, k2, k, ne))
3903
3904def Laws.hmap_size_put_new(K, V, hash, eq, sound, m, wf, k, v, miss):
3905  h.sz_put_new(~K, ~V, ~hash, ~eq, ~sound, 32n, 1, m, k, v, wf, miss)
3906
3907def Laws.hmap_size_put_replace(K, V, hash, eq, m, k, v, w, hit):
3908  h.sz_put_hit(~K, ~V, ~eq, 32n, 1, m, hash(k), k, v, w, hit)
3909
3910def Laws.hmap_size_del(K, V, hash, eq, m, k, w, hit):
3911  h.sz_del_hit(~K, ~V, ~eq, 32n, 1, m, hash(k), k, w, hit)
3912
3913def Laws.hmap_size_del_missing(K, V, hash, eq, m, k, miss):
3914  h.sz_del_miss(~K, ~V, ~eq, 32n, 1, m, hash(k), k, miss)
3915
3916def Laws.hmap_collision_get(K, V, hash, eq, refl, sound, m, wf, k1, k2, ne, same, v1, v2):
3917  +m1 = M.HMap.put(~K, ~V, ~hash, ~eq, m, k1, v1)
3918  Equal.trans(Maybe<&2, V>,
3919    M.HMap.get(~K, ~V, ~hash, ~eq, M.HMap.put(~K, ~V, ~hash, ~eq, m1, k2, v2), k1),
3920    M.HMap.get(~K, ~V, ~hash, ~eq, m1, k1), Some{v1},
3921    h.gp_other(~K, ~V, ~hash, ~eq, ~sound, 32n, 1, m1, hash(k2), k2, k1, v2,
3922      h.wf_put(~K, ~V, ~hash, ~eq, ~refl, ~sound, 32n, 1, m, k1, v1, wf),
3923      h.ne_f(~K, ~eq, ~sound, k2, k1, ne)),
3924    h.gp_same(~K, ~V, ~hash, ~eq, ~refl, 32n, 1, m, hash(k1), k1, v1, {==}, wf))
3925
3926def Laws.hmap_collision_size(K, V, hash, eq, refl, sound, m, wf, k1, k2, ne, same, v1, v2, miss1, miss2):
3927  +m1 = M.HMap.put(~K, ~V, ~hash, ~eq, m, k1, v1)
3928  Equal.trans(Nat, M.HMap.size(K, V, M.HMap.put(~K, ~V, ~hash, ~eq, m1, k2, v2)),
3929    1n+M.HMap.size(K, V, m1), 2n+M.HMap.size(K, V, m),
3930    Laws.hmap_size_put_new(~K, ~V, ~hash, ~eq, ~sound, m1,
3931      Laws.hmap_put_wf(~K, ~V, ~hash, ~eq, ~refl, ~sound, m, wf, k1, v1), k2, v2,
3932      Equal.trans(Maybe<&2, V>, M.HMap.get(~K, ~V, ~hash, ~eq, m1, k2),
3933        M.HMap.get(~K, ~V, ~hash, ~eq, m, k2), None{},
3934        Laws.hmap_get_put_other_key(~K, ~V, ~hash, ~eq, ~sound, m, wf, k1, k2, ne, v1), miss2)),
3935    Equal.cong(Nat, Nat, x => 1n+x, M.HMap.size(K, V, m1), 1n+M.HMap.size(K, V, m),
3936      Laws.hmap_size_put_new(~K, ~V, ~hash, ~eq, ~sound, m, wf, k1, v1, miss1)))
3937
3938# --- string order ----------------------------------------------------------------
3939
3940# A comparison equal to LT is not one whose is_lt is False.
3941def lt_absurd(-A: Type, -c: Cmp, f: {Cmp.is_lt(c) == False{} : Bool}, e: {c == LT{} : Cmp}) -> A:
3942  Empty.absurd(A, MBool.false_ne_true()(Equal.trans(Bool, False{}, Cmp.is_lt(c), True{},
3943    Equal.sym(Bool, Cmp.is_lt(c), False{}, f), lt_true(c, e))))
3944
3945def ncmp_refl(n: Nat) -> {Nat.cmp(n, n) == EQ{} : Cmp}:
3946  match n:
3947    case 0n:
3948      {==}
3949    case 1n+p:
3950      ncmp_refl(p)
3951
3952def ncmp_eq(a: Nat, b: Nat, e: {Nat.cmp(a, b) == EQ{} : Cmp}) -> {a == b : Nat}:
3953  match a b:
3954    case 0n 0n:
3955      {==}
3956    case 0n 1n+q:
3957      ne_absurd({0n == 1n+q : Nat}, LT{}, {==}, e)
3958    case 1n+p 0n:
3959      ne_absurd({1n+p == 0n : Nat}, GT{}, {==}, e)
3960    case 1n+p 1n+q:
3961      %ncmp_eq(p, q, e) : {1n+p == 1n+_ : Nat}
3962      {==}
3963
3964def ncmp_flip(a: Nat, b: Nat) -> {Nat.cmp(b, a) == Laws.flip(Nat.cmp(a, b)) : Cmp}:
3965  match a b:
3966    case 0n 0n:
3967      {==}
3968    case 0n 1n+q:
3969      {==}
3970    case 1n+p 0n:
3971      {==}
3972    case 1n+p 1n+q:
3973      ncmp_flip(p, q)
3974
3975def ncmp_trans(
3976  a: Nat, b: Nat, c: Nat, e1: {Nat.cmp(a, b) == LT{} : Cmp}, e2: {Nat.cmp(b, c) == LT{} : Cmp}
3977) -> {Nat.cmp(a, c) == LT{} : Cmp}:
3978  match a b c:
3979    case 0n 0n _:
3980      lt_absurd({Nat.cmp(0n, c) == LT{} : Cmp}, EQ{}, {==}, e1)
3981    case 1n+p 0n _:
3982      lt_absurd({Nat.cmp(1n+p, c) == LT{} : Cmp}, GT{}, {==}, e1)
3983    case _ 1n+q 0n:
3984      lt_absurd({Nat.cmp(a, 0n) == LT{} : Cmp}, GT{}, {==}, e2)
3985    case 0n 1n+q 1n+r:
3986      {==}
3987    case 1n+p 1n+q 1n+r:
3988      ncmp_trans(p, q, r, e1, e2)
3989
3990def ucmp_nat(+a: U32, +b: U32) -> {Nat.cmp(U32.to_nat(a), U32.to_nat(b)) == U32.cmp(a, b) : Cmp}:
3991  Equal.sym(Cmp, U32.cmp(a, b), Nat.cmp(U32.to_nat(a), U32.to_nat(b)), Lemmas.u32_cmp_nat(a, b))
3992
3993def ucmp_refl(+x: U32) -> {U32.cmp(x, x) == EQ{} : Cmp}:
3994  %ucmp_nat(x, x) : {_ == EQ{} : Cmp}
3995  ncmp_refl(U32.to_nat(x))
3996
3997def ucmp_eq(+x: U32, +y: U32, e: {U32.cmp(x, y) == EQ{} : Cmp}) -> {x == y : U32}:
3998  Lemmas.u32_to_nat_inj(x, y, ncmp_eq(U32.to_nat(x), U32.to_nat(y),
3999    Equal.trans(Cmp, Nat.cmp(U32.to_nat(x), U32.to_nat(y)), U32.cmp(x, y), EQ{}, ucmp_nat(x, y), e)))
4000
4001def ucmp_flip(+x: U32, +y: U32) -> {U32.cmp(y, x) == Laws.flip(U32.cmp(x, y)) : Cmp}:
4002  %ucmp_nat(y, x) : {_ == Laws.flip(U32.cmp(x, y)) : Cmp}
4003  %ucmp_nat(x, y) : {Nat.cmp(U32.to_nat(y), U32.to_nat(x)) == Laws.flip(_) : Cmp}
4004  ncmp_flip(U32.to_nat(x), U32.to_nat(y))
4005
4006def ucmp_lt(+x: U32, +y: U32, e: {U32.cmp(x, y) == LT{} : Cmp}) -> {Nat.cmp(U32.to_nat(x), U32.to_nat(y)) == LT{} : Cmp}:
4007  Equal.trans(Cmp, Nat.cmp(U32.to_nat(x), U32.to_nat(y)), U32.cmp(x, y), LT{}, ucmp_nat(x, y), e)
4008
4009def ucmp_trans(
4010  +x: U32, +y: U32, +z: U32, e1: {U32.cmp(x, y) == LT{} : Cmp}, e2: {U32.cmp(y, z) == LT{} : Cmp}
4011) -> {U32.cmp(x, z) == LT{} : Cmp}:
4012  %ucmp_nat(x, z) : {_ == LT{} : Cmp}
4013  ncmp_trans(U32.to_nat(x), U32.to_nat(y), U32.to_nat(z), ucmp_lt(x, y, e1), ucmp_lt(y, z, e2))
4014
4015def Laws.order_string_refl(x):
4016  match x:
4017    case SNil{}:
4018      {==}
4019    case SCon{Chr{+c}, t}:
4020      %Equal.sym(Cmp, U32.cmp(c, c), EQ{}, ucmp_refl(c)) : {Order.string.fin(_, Order.string(t, t)) == EQ{} : Cmp}
4021      Laws.order_string_refl(t)
4022
4023# One step of eq on the heads a and b, with the tails' result as ih.
4024def seq.step(
4025  +a: U32, +b: U32, +s: String, +t: String, c: Cmp, h: {U32.cmp(a, b) == c : Cmp},
4026  e: {Order.string.fin(c, Order.string(s, t)) == EQ{} : Cmp},
4027  ih: {Order.string(s, t) == EQ{} : Cmp} -> {s == t : String}
4028) -> {SCon{Chr{a}, s} == SCon{Chr{b}, t} : String}:
4029  match c:
4030    case LT{}:
4031      ne_absurd({SCon{Chr{a}, s} == SCon{Chr{b}, t} : String}, LT{}, {==}, e)
4032    case EQ{}:
4033      +ea = ucmp_eq(a, b, h)
4034      +es = ih(e)
4035      %ea : {SCon{Chr{a}, s} == SCon{Chr{_}, t} : String}
4036      %es : {SCon{Chr{a}, s} == SCon{Chr{a}, _} : String}
4037      {==}
4038    case GT{}:
4039      ne_absurd({SCon{Chr{a}, s} == SCon{Chr{b}, t} : String}, GT{}, {==}, e)
4040
4041def Laws.order_string_eq(x, y, e):
4042  match x y:
4043    case SNil{} SNil{}:
4044      {==}
4045    case SNil{} SCon{Chr{b}, t}:
4046      ne_absurd({SNil{} == SCon{Chr{b}, t} : String}, LT{}, {==}, e)
4047    case SCon{Chr{a}, s} SNil{}:
4048      ne_absurd({SCon{Chr{a}, s} == SNil{} : String}, GT{}, {==}, e)
4049    case SCon{Chr{+a}, +s} SCon{Chr{+b}, +t}:
4050      seq.step(a, b, s, t, U32.cmp(a, b), {==}, e, p => Laws.order_string_eq(s, t, p))
4051
4052def sfin_flip(c: Cmp, -r: Cmp) -> {Order.string.fin(Laws.flip(c), Laws.flip(r)) == Laws.flip(Order.string.fin(c, r)) : Cmp}:
4053  match c:
4054    case LT{}:
4055      {==}
4056    case EQ{}:
4057      {==}
4058    case GT{}:
4059      {==}
4060
4061def Laws.order_string_flip(x, y):
4062  match x y:
4063    case SNil{} SNil{}:
4064      {==}
4065    case SNil{} SCon{Chr{b}, t}:
4066      {==}
4067    case SCon{Chr{a}, s} SNil{}:
4068      {==}
4069    case SCon{Chr{+a}, +s} SCon{Chr{+b}, +t}:
4070      %Equal.sym(Cmp, U32.cmp(b, a), Laws.flip(U32.cmp(a, b)), ucmp_flip(a, b)) :
4071        {Order.string.fin(_, Order.string(t, s)) == Laws.flip(Order.string.fin(U32.cmp(a, b), Order.string(s, t))) : Cmp}
4072      %Equal.sym(Cmp, Order.string(t, s), Laws.flip(Order.string(s, t)), Laws.order_string_flip(s, t)) :
4073        {Order.string.fin(Laws.flip(U32.cmp(a, b)), _) == Laws.flip(Order.string.fin(U32.cmp(a, b), Order.string(s, t))) : Cmp}
4074      sfin_flip(U32.cmp(a, b), Order.string(s, t))
4075
4076# One step of transitivity on the heads a < b < c, with the tails' result as ih.
4077def strans.step(
4078  +a: U32, +b: U32, +c: U32, -s: String, -t: String, -u: String, c1: Cmp, c2: Cmp,
4079  h1: {U32.cmp(a, b) == c1 : Cmp}, h2: {U32.cmp(b, c) == c2 : Cmp},
4080  e1: {Order.string.fin(c1, Order.string(s, t)) == LT{} : Cmp},
4081  e2: {Order.string.fin(c2, Order.string(t, u)) == LT{} : Cmp},
4082  ih: {Order.string(s, t) == LT{} : Cmp} -> {Order.string(t, u) == LT{} : Cmp} -> {Order.string(s, u) == LT{} : Cmp}
4083) -> {Order.string.fin(U32.cmp(a, c), Order.string(s, u)) == LT{} : Cmp}:
4084  match c1 c2:
4085    case LT{} LT{}:
4086      %Equal.sym(Cmp, U32.cmp(a, c), LT{}, ucmp_trans(a, b, c, h1, h2)) : {Order.string.fin(_, Order.string(s, u)) == LT{} : Cmp}
4087      {==}
4088    case LT{} EQ{}:
4089      +ebc = ucmp_eq(b, c, h2)
4090      +eac = rw(U32, w => {U32.cmp(a, w) == LT{} : Cmp}, c, b, Equal.sym(U32, b, c, ebc), h1)
4091      %Equal.sym(Cmp, U32.cmp(a, c), LT{}, eac) : {Order.string.fin(_, Order.string(s, u)) == LT{} : Cmp}
4092      {==}
4093    case EQ{} LT{}:
4094      +eab = ucmp_eq(a, b, h1)
4095      +eac = rw(U32, w => {U32.cmp(w, c) == LT{} : Cmp}, a, b, eab, h2)
4096      %Equal.sym(Cmp, U32.cmp(a, c), LT{}, eac) : {Order.string.fin(_, Order.string(s, u)) == LT{} : Cmp}
4097      {==}
4098    case EQ{} EQ{}:
4099      +eca = Equal.sym(U32, a, c, Equal.trans(U32, a, b, c, ucmp_eq(a, b, h1), ucmp_eq(b, c, h2)))
4100      +eac = rw(U32, w => {U32.cmp(a, w) == EQ{} : Cmp}, c, a, eca, ucmp_refl(a))
4101      %Equal.sym(Cmp, U32.cmp(a, c), EQ{}, eac) : {Order.string.fin(_, Order.string(s, u)) == LT{} : Cmp}
4102      ih(e1, e2)
4103    case GT{} _:
4104      lt_absurd({Order.string.fin(U32.cmp(a, c), Order.string(s, u)) == LT{} : Cmp}, GT{}, {==}, e1)
4105    case _ GT{}:
4106      lt_absurd({Order.string.fin(U32.cmp(a, c), Order.string(s, u)) == LT{} : Cmp}, GT{}, {==}, e2)
4107
4108def Laws.order_string_trans(x, y, z, e1, e2):
4109  match x y z:
4110    case SNil{} SNil{} _:
4111      lt_absurd({Order.string(SNil{}, z) == LT{} : Cmp}, EQ{}, {==}, e1)
4112    case SCon{Chr{a}, s} SNil{} _:
4113      lt_absurd({Order.string(SCon{Chr{a}, s}, z) == LT{} : Cmp}, GT{}, {==}, e1)
4114    case SNil{} SCon{Chr{b}, t} SNil{}:
4115      lt_absurd({Order.string(SNil{}, SNil{}) == LT{} : Cmp}, GT{}, {==}, e2)
4116    case SCon{Chr{a}, s} SCon{Chr{b}, t} SNil{}:
4117      lt_absurd({Order.string(SCon{Chr{a}, s}, SNil{}) == LT{} : Cmp}, GT{}, {==}, e2)
4118    case SNil{} SCon{Chr{b}, t} SCon{Chr{c}, u}:
4119      {==}
4120    case SCon{Chr{+a}, +s} SCon{Chr{+b}, +t} SCon{Chr{+c}, +u}:
4121      strans.step(a, b, c, s, t, u, U32.cmp(a, b), U32.cmp(b, c), {==}, {==}, e1, e2,
4122        p => q => Laws.order_string_trans(s, t, u, p, q))
4123
4124def Laws.order_string_fixtures():
4125  {==}