@effekt-lang/effekt 0.17.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,992 @@
1
+ module map
2
+
3
+ /// Ordered finite immutable map, backed by balanced binary trees of logarithmic depth.
4
+ record Map[K, V](tree: internal::Tree[K, V], compare: (K, K) => Ordering at {})
5
+
6
+ /// Create a new empty map using a pure, first-class comparison function.
7
+ ///
8
+ /// O(1)
9
+ def empty[K, V](compare: (K, K) => Ordering at {}): Map[K, V] =
10
+ Map(internal::empty(), compare)
11
+
12
+ /// Create a new empty map using a generic comparison function.
13
+ /// Only available on JavaScript backends!
14
+ ///
15
+ /// O(1)
16
+ def emptyGeneric[K, V](): Map[K, V] =
17
+ Map(
18
+ internal::empty(),
19
+ box { (left: K, right: K) => genericCompare(left, right) }
20
+ )
21
+
22
+ /// Check if map `m` is empty.
23
+ ///
24
+ /// O(1)
25
+ def isEmpty[K, V](m: Map[K, V]): Bool = internal::isEmpty(m.tree)
26
+
27
+ /// Check if map `m` is nonempty.
28
+ ///
29
+ /// O(1)
30
+ def nonEmpty[K, V](m: Map[K, V]): Bool = internal::nonEmpty(m.tree)
31
+
32
+ /// Create a new map containing the mapping from `k` to `v` and a pure, first-class comparison function.
33
+ ///
34
+ /// O(1)
35
+ def singleton[K, V](k: K, v: V, compare: (K, K) => Ordering at {}): Map[K, V] =
36
+ Map(internal::singleton(k, v), compare)
37
+
38
+ /// Create a new map containing the mapping from `k` to `v` using a generic comparison function.
39
+ /// Only available on the JavaScript backends!
40
+ ///
41
+ /// O(1)
42
+ def singletonGeneric[K, V](k: K, v: V): Map[K, V] =
43
+ Map(
44
+ internal::singleton(k, v),
45
+ box { (left: K, right: K) => genericCompare(left, right) }
46
+ )
47
+
48
+ /// Get the size of the map (the number of keys/values).
49
+ ///
50
+ /// O(1)
51
+ def size[K, V](m: Map[K, V]): Int = internal::size(m.tree)
52
+
53
+ /// Insert a new key `k` and value `v` into the map `m`.
54
+ /// If the key `k` is already present in `m`, its associated value is replaced with `v`.
55
+ ///
56
+ /// O(log N)
57
+ def put[K, V](m: Map[K, V], k: K, v: V): Map[K, V] = {
58
+ val newTree = internal::put(m.tree, m.compare, k, v)
59
+ Map(newTree, m.compare)
60
+ }
61
+
62
+ /// Insert a new key `k` and value `v` into the map `m`.
63
+ /// If the key `k` is already present in `m` with value `v2`, the function `combine` is called on `k`, `v`, `v2`.
64
+ ///
65
+ /// O(log N)
66
+ def putWithKey[K, V](m: Map[K, V], k: K, v: V) { combine: (K, V, V) => V }: Map[K, V] = {
67
+ val newTree = internal::putWithKey(m.tree, m.compare, k, v) {combine}
68
+ Map(newTree, m.compare)
69
+ }
70
+
71
+ /// Lookup the value at a key `k` in the map `m`.
72
+ ///
73
+ /// O(log N)
74
+ def get[K, V](m: Map[K, V], k: K): Option[V] = internal::get(m.tree, m.compare, k)
75
+
76
+ /// Lookup the value at a key `k` in the map `m`.
77
+ /// If there is no key, use the `default` block to retrieve a default value.
78
+ ///
79
+ /// O(log N)
80
+ def getOrElse[K, V](m: Map[K, V], k: K) { default: => V }: V =
81
+ internal::get(m.tree, m.compare, k) match {
82
+ case None() => default()
83
+ case Some(v) => v
84
+ }
85
+
86
+ /// Check if map `m` contains a key `k`.
87
+ ///
88
+ /// O(log N)
89
+ def contains[K, V](m: Map[K, V], k: K): Bool =
90
+ internal::get(m.tree, m.compare, k) match {
91
+ case None() => false
92
+ case Some(v) => true
93
+ }
94
+
95
+ /// Get minimum in the map `m`.
96
+ ///
97
+ /// O(log N)
98
+ def getMin[K, V](m: Map[K, V]): Option[(K, V)] = internal::getMin(m.tree)
99
+
100
+ /// Get maximum in the map `m`.
101
+ ///
102
+ /// O(log N)
103
+ def getMax[K, V](m: Map[K, V]): Option[(K, V)] = internal::getMax(m.tree)
104
+
105
+ /// Tree a function `f` over values in map `m`.
106
+ ///
107
+ /// O(N)
108
+ def map[K, V1, V2](m: Map[K, V1]) { f: (K, V1) => V2 }: Map[K, V2] = {
109
+ val newTree = internal::map(m.tree) {f}
110
+ Map(newTree, m.compare)
111
+ }
112
+
113
+ /// Tree a function `f` over values in map `m`.
114
+ ///
115
+ /// O(N)
116
+ def map[K, V1, V2](m: Map[K, V1]) { f: V1 => V2 }: Map[K, V2] = {
117
+ m.map { (_k, v) => f(v) }
118
+ }
119
+
120
+ /// Tree a function `f` over values in map `m`, keeping only the values where `f` returns `Some(...)`
121
+ ///
122
+ /// O(N)
123
+ def mapMaybe[K, V1, V2](m: Map[K, V1]) { f: (K, V1) => Option[V2] }: Map[K, V2] = {
124
+ val newTree = internal::mapMaybe(m.tree) {f}
125
+ Map(newTree, m.compare)
126
+ }
127
+
128
+ /// Filters a map `m` with a `shouldKeep` function,
129
+ /// keeping only the elements where `shouldKeep` returns `true`.
130
+ ///
131
+ /// Law: `m.filter { f } === m.mapMaybe { (k, v) => if (f(k, v)) Some(v) else None() }`
132
+ ///
133
+ /// O(N)
134
+ def filter[K, V](m: Map[K, V]) { shouldKeep: (K, V) => Bool }: Map[K, V] = {
135
+ val newTree = internal::filter(m.tree) {shouldKeep}
136
+ Map(newTree, m.compare)
137
+ }
138
+
139
+ /// Filters a map `m` with a `shouldKeep` function,
140
+ /// keeping only the values where `shouldKeep` returns `true`.
141
+ ///
142
+ /// O(N)
143
+ def filter[K, V](m: Map[K, V]) { shouldKeep: V => Bool }: Map[K, V] =
144
+ m.filter { (_k, v) => shouldKeep(v) }
145
+
146
+ /// Traverse all keys and their associated values in map `m` in order,
147
+ /// running the function `action` on a key and its associated value.
148
+ ///
149
+ /// Law: `m.foreach { action } === m.toList.foreach { action }`
150
+ ///
151
+ /// O(N)
152
+ ///
153
+ /// TODO: Support {Control} for early exits.
154
+ def foreach[K, V](m: Map[K, V]) { action: (K, V) => Unit }: Unit =
155
+ internal::foreach(m.tree) {action}
156
+
157
+ /// Convert a map `m` into a list of (key, value) pairs.
158
+ ///
159
+ /// O(N)
160
+ def toList[K, V](m: Map[K, V]): List[(K, V)] = {
161
+ var acc = Nil()
162
+ m.foreach { (k, v) =>
163
+ acc = Cons((k, v), acc)
164
+ }
165
+ acc.reverse
166
+ }
167
+
168
+ /// Get a list of keys of the map `m`.
169
+ ///
170
+ /// O(N)
171
+ def keys[K, V](m: Map[K, V]): List[K] = {
172
+ var acc = Nil()
173
+ m.foreach { (k, _v) =>
174
+ acc = Cons(k, acc)
175
+ }
176
+ acc.reverse
177
+ }
178
+
179
+ /// Get a list of values of the map `m`.
180
+ ///
181
+ /// O(N)
182
+ def values[K, V](m: Map[K, V]): List[V] = {
183
+ var acc = Nil()
184
+ m.foreach { (_k, v) =>
185
+ acc = Cons(v, acc)
186
+ }
187
+ acc.reverse
188
+ }
189
+
190
+ /// Create a map from a list of (key, value) pairs and a pure, first-class comparison function.
191
+ /// If the list contains more than one value for the same key,
192
+ /// only the last value is used in the map.
193
+ ///
194
+ /// O(N) if the list is sorted by key,
195
+ /// O(N log N) otherwise
196
+ def fromList[K, V](pairs: List[(K, V)], compare: (K, K) => Ordering at {}): Map[K, V] =
197
+ Map(internal::fromList(pairs, compare), compare)
198
+
199
+ /// Create a map from a list of (key, value) pairs and a generic comparison function.
200
+ /// If the list contains more than one value for the same key,
201
+ /// only the last value is used in the map.
202
+ /// Works only on JavaScript backends!
203
+ ///
204
+ /// O(N) if the list is sorted by key,
205
+ /// O(N log N) otherwise
206
+ def fromListGeneric[K, V](pairs: List[(K, V)]): Map[K, V] = {
207
+ val compare: (K, K) => Ordering at {} = box { (left, right) => genericCompare(left, right) }
208
+ Map(internal::fromList(pairs, compare), compare)
209
+ }
210
+
211
+ /// Remove a key `k` from a map `m`.
212
+ /// If `k` is not in `m`, `m` is returned.
213
+ ///
214
+ /// O(log N)
215
+ def delete[K, V](m: Map[K, V], k: K): Map[K, V] = {
216
+ val newTree = internal::delete(m.tree, m.compare, k)
217
+ Map(newTree, m.compare)
218
+ }
219
+
220
+ /// Can be used to insert, delete, or update a value.
221
+ /// Law: `get(m.alter(k){f}, k) === f(get(m, k))`
222
+ ///
223
+ /// O(log N)
224
+ def alter[K, V](m: Map[K, V], k: K) { f: Option[V] => Option[V] }: Map[K, V] = {
225
+ val newTree = internal::alter(m.tree, m.compare, k) {f}
226
+ Map(newTree, m.compare)
227
+ }
228
+
229
+ /// Update or delete a value associated with key `k` in map `m`.
230
+ ///
231
+ /// O(log N)
232
+ def update[K, V](m: Map[K, V], k: K) { f: (K, V) => Option[V] }: Map[K, V] = {
233
+ val newTree = internal::update(m.tree, m.compare, k) {f}
234
+ Map(newTree, m.compare)
235
+ }
236
+
237
+ /// Update or delete a value associated with key `k` in map `m`.
238
+ ///
239
+ /// O(log N)
240
+ def update[K, V](m: Map[K, V], k: K) { f: V => Option[V] }: Map[K, V] =
241
+ m.update(k) { (_k, v) => f(v) }
242
+
243
+ /// Get `n`-th (key, value) pair in the map `m`.
244
+ ///
245
+ /// O(log N)
246
+ def getIndex[K, V](m: Map[K, V], n: Int): Option[(K, V)] =
247
+ internal::getIndex(m.tree, n)
248
+
249
+ /// Construct a new map which contains all elements of `m1`
250
+ /// except those where the key is found in `m2`.
251
+ /// Uses an explicit pure, first-class comparison function.
252
+ ///
253
+ /// O(???)
254
+ def difference[K, V](m1: Map[K, V], m2: Map[K, V], compare: (K, K) => Ordering at {}) = {
255
+ val newTree = internal::difference(m1.tree, m2.tree, compare)
256
+ Map(newTree, compare)
257
+ }
258
+
259
+ /// Construct a new map which contains all elements of `m1`
260
+ /// except those where the key is found in `m2`.
261
+ /// Uses the comparison function from `m1`.
262
+ ///
263
+ /// O(???)
264
+ def difference[K, V](m1: Map[K, V], m2: Map[K, V]) = {
265
+ val newTree = internal::difference(m1.tree, m2.tree, m1.compare)
266
+ Map(newTree, m1.compare)
267
+ }
268
+
269
+ /// Construct a new map which contains the elements of both `m1` and `m2`.
270
+ /// When a key is associated with a value in both `m1` and `m2`, the new value is determined using the `combine` function.
271
+ /// Uses an explicit pure, first-class comparison function.
272
+ ///
273
+ /// O(???)
274
+ def union[K, V](m1: Map[K, V], m2: Map[K, V], compare: (K, K) => Ordering at {}) { combine: (K, V, V) => V }: Map[K, V] = {
275
+ val newTree = internal::union(m1.tree, m2.tree, compare) {combine}
276
+ Map(newTree, compare)
277
+ }
278
+
279
+ /// Construct a new map which contains the elements of both `m1` and `m2`.
280
+ /// When a key is associated with a value in both `m1` and `m2`, the new value is determined using the `combine` function.
281
+ /// Uses an explicit pure, first-class comparison function.
282
+ ///
283
+ /// O(???)
284
+ def union[K, V](m1: Map[K, V], m2: Map[K, V], compare: (K, K) => Ordering at {}) { combine: (V, V) => V }: Map[K, V] =
285
+ union(m1, m2, compare) { (k, v1, v2) => combine(v1, v2) }
286
+
287
+ /// Construct a new map which contains the elements of both `m1` and `m2`.
288
+ /// Left-biased: Uses values from `m1` if there are duplicate keys and
289
+ /// uses the comparison function from `m1`.
290
+ ///
291
+ /// O(???)
292
+ def union[K, V](m1: Map[K, V], m2: Map[K, V]): Map[K, V] =
293
+ union[K, V](m1, m2, m1.compare) { (k, v1, v2) => v1 }
294
+
295
+ /// Construct a new map which combines all elements that are in both `m1` and `m2` using the `combine` function.
296
+ ///
297
+ /// O(???)
298
+ def intersection[K, A, B, C](m1: Map[K, A], m2: Map[K, B], compare: (K, K) => Ordering at {}) { combine: (K, A, B) => C }: Map[K, C] = {
299
+ val newTree = internal::intersection(m1.tree, m2.tree, compare) {combine}
300
+ Map(newTree, compare)
301
+ }
302
+
303
+ /// Construct a new map which combines all elements that are in both `m1` and `m2` using the `combine` function.
304
+ ///
305
+ /// O(???)
306
+ def intersection[K, A, B, C](m1: Map[K, A], m2: Map[K, B], compare: (K, K) => Ordering at {}) { combine: (A, B) => C }: Map[K, C] =
307
+ m1.intersection[K, A, B, C](m2, compare) { (k, v1, v2) => combine(v1, v2) }
308
+
309
+ /// Construct a new map which combines all elements that are in both `m1` and `m2`.
310
+ /// Left-biased: Always uses values from `m1` and the comparison function from `m1`.
311
+ ///
312
+ /// O(???)
313
+ def intersection[K, A, B](m1: Map[K, A], m2: Map[K, B]): Map[K, A] =
314
+ m1.intersection[K, A, B, A](m2, m1.compare) { (k, v1, v2) => v1 }
315
+
316
+ /// Please don't directly use:
317
+ /// - the `Tree` type
318
+ /// - its internal constructors `Bin` & `Tip`,
319
+ /// - and these functions.
320
+ /// As they might change down the line and are not considered stable / public.
321
+ namespace internal {
322
+ /// Balanced binary trees of logarithmic depth.
323
+ type Tree[K, V] {
324
+ Bin(size: Int, k: K, v: V, left: Tree[K, V], right: Tree[K, V]);
325
+ Tip()
326
+ }
327
+
328
+ /// Create a new empty tree.
329
+ ///
330
+ /// O(1)
331
+ def empty[K, V](): Tree[K, V] = Tip()
332
+
333
+ /// Check if tree `m` is empty.
334
+ ///
335
+ /// O(1)
336
+ def isEmpty[K, V](m: Tree[K, V]): Bool =
337
+ m match {
338
+ case Tip() => true
339
+ case _ => false
340
+ }
341
+
342
+ /// Check if tree `m` is nonempty.
343
+ ///
344
+ /// O(1)
345
+ def nonEmpty[K, V](m: Tree[K, V]): Bool =
346
+ m match {
347
+ case Tip() => false
348
+ case _ => true
349
+ }
350
+
351
+ /// Create a new tree containing only the mapping from `k` to `v`.
352
+ ///
353
+ /// O(1)
354
+ def singleton[K, V](k: K, v: V): Tree[K, V] =
355
+ Bin(1, k, v, Tip(), Tip())
356
+
357
+ /// Get the size of the tree (the number of keys/values).
358
+ ///
359
+ /// O(1)
360
+ def size[K, V](m: Tree[K, V]): Int =
361
+ m match {
362
+ case Tip() => 0
363
+ case Bin(size, _, _, _, _) => size
364
+ }
365
+
366
+ /// Insert a new key `k` and value `v` into the tree `m`.
367
+ /// If the key `k` is already present in `m`, its associated value is replaced with `v`.
368
+ ///
369
+ /// O(log N)
370
+ def put[K, V](m: Tree[K, V], compare: (K, K) => Ordering at {}, k: K, v: V): Tree[K, V] =
371
+ m match {
372
+ case Tip() => singleton(k, v)
373
+ case Bin(size, k2, v2, l, r) =>
374
+ compare(k, k2) match {
375
+ case Less() => balance(k2, v2, put(l, compare, k, v), r)
376
+ case Greater() => balance(k2, v2, l, put(r, compare, k, v))
377
+ case Equal() => Bin(size, k, v, l, r)
378
+ }
379
+ }
380
+
381
+ /// Insert a new key `k` and value `v` into the tree `m`.
382
+ /// If the key `k` is already present in `m` with value `v2`, the function `combine` is called on `k`, `v`, `v2`.
383
+ ///
384
+ /// O(log N)
385
+ def putWithKey[K, V](m: Tree[K, V], compare: (K, K) => Ordering at {}, k: K, v: V) { combine: (K, V, V) => V } : Tree[K, V] =
386
+ m match {
387
+ case Tip() => singleton(k, v)
388
+ case Bin(size, k2, v2, l, r) =>
389
+ compare(k, k2) match {
390
+ case Less() => balance(k2, v2, l.putWithKey(compare, k, v){combine}, r)
391
+ case Greater() => balance(k2, v2, l, r.putWithKey(compare, k, v){combine})
392
+ case Equal() => Bin(size, k, combine(k, v, v2), l, r)
393
+ }
394
+ }
395
+
396
+ /// Lookup the value at a key `k` in the tree `m`.
397
+ ///
398
+ /// O(log N)
399
+ def get[K, V](m: Tree[K, V], compare: (K, K) => Ordering at {}, k: K): Option[V] =
400
+ m match {
401
+ case Tip() => None()
402
+ case Bin(size, k2, v, l, r) =>
403
+ compare(k, k2) match {
404
+ case Less() => get(l, compare, k)
405
+ case Greater() => get(r, compare, k)
406
+ case Equal() => Some(v)
407
+ }
408
+ }
409
+
410
+ /// Get minimum in the tree `m`.
411
+ ///
412
+ /// O(log N)
413
+ def getMin[K, V](m: Tree[K, V]): Option[(K, V)] = {
414
+ def go(k: K, v: V, m: Tree[K, V]): (K, V) = {
415
+ m match {
416
+ case Tip() => (k, v)
417
+ case Bin(_, k2, v2, l, _) => go(k2, v2, l)
418
+ }
419
+ }
420
+
421
+ m match {
422
+ case Tip() => None()
423
+ case Bin(_, k, v, l, _) => Some(go(k, v, l))
424
+ }
425
+ }
426
+
427
+ /// Get maximum in the tree `m`.
428
+ ///
429
+ /// O(log N)
430
+ def getMax[K, V](m: Tree[K, V]): Option[(K, V)] = {
431
+ def go(k: K, v: V, m: Tree[K, V]): (K, V) = {
432
+ m match {
433
+ case Tip() => (k, v)
434
+ case Bin(_, k2, v2, _, r) => go(k2, v2, r)
435
+ }
436
+ }
437
+
438
+ m match {
439
+ case Tip() => None()
440
+ case Bin(_, k, v, _, r) => Some(go(k, v, r))
441
+ }
442
+ }
443
+
444
+ /// Forgets the values of a tree, setting them all to `(): Unit`.
445
+ /// Used by `set`s internally.
446
+ ///
447
+ /// Law: `m.forget === m.map { (_k, _v) => () }`
448
+ ///
449
+ /// O(N)
450
+ def forget[K, V](m: Tree[K, V]): Tree[K, Unit] =
451
+ m match {
452
+ case Tip() => Tip()
453
+ case Bin(size, k, v, l, r) =>
454
+ Bin(size, k, (), l.forget, r.forget)
455
+ }
456
+
457
+ /// Tree a function `f` over values in tree `m`.
458
+ ///
459
+ /// O(N)
460
+ def map[K, V1, V2](m: Tree[K, V1]) { f : (K, V1) => V2 }: Tree[K, V2] =
461
+ m match {
462
+ case Tip() => Tip()
463
+ case Bin(size, k, v, l, r) =>
464
+ Bin(size, k, f(k, v), l.map {f}, r.map {f})
465
+ }
466
+
467
+ /// Tree a function `f` over values in tree `m`, keeping only the values where `f` returns `Some(...)`
468
+ ///
469
+ /// O(N)
470
+ def mapMaybe[K, V1, V2](m: Tree[K, V1]) { f : (K, V1) => Option[V2] }: Tree[K, V2] =
471
+ m match {
472
+ case Tip() => Tip()
473
+ case Bin(size, k, v, l, r) => f(k, v) match {
474
+ case Some(v2) => link(k, v2, l.mapMaybe {f}, r.mapMaybe {f})
475
+ case None() => link2(l.mapMaybe {f}, r.mapMaybe {f})
476
+ }
477
+ }
478
+
479
+ /// Filters a tree `m` with a `shouldKeep` function,
480
+ /// keeping only the elements where `shouldKeep` returns `true`.
481
+ ///
482
+ /// Law: `m.filter { f } === m.mapMaybe { (k, v) => if (f(k, v)) Some(v) else None() }`
483
+ ///
484
+ /// O(N)
485
+ def filter[K, V](m: Tree[K, V]) { shouldKeep: (K, V) => Bool }: Tree[K, V] = {
486
+ def go(tree: Tree[K, V]): (Tree[K, V], Bool) = tree match {
487
+ case Tip() => (Tip(), false)
488
+ case Bin(size, k, v, l, r) =>
489
+ val (l2, lchanged) = go(l)
490
+ val (r2, rchanged) = go(r)
491
+ if (shouldKeep(k, v)) {
492
+ val changed = lchanged || rchanged
493
+ val tree2 = if (changed) {
494
+ link(k, v, l2, r2)
495
+ } else {
496
+ tree
497
+ }
498
+ (tree2, changed)
499
+ } else {
500
+ (link2(l2, r2), true)
501
+ }
502
+ }
503
+
504
+ go(m).first
505
+ }
506
+
507
+ /// Traverse all keys and their associated values in tree `m` in order,
508
+ /// running the function `action` on a key and its associated value.
509
+ ///
510
+ /// Law: `m.foreach { action } === m.toList.foreach { action }`
511
+ ///
512
+ /// O(N)
513
+ ///
514
+ /// TODO: Support {Control} for early exits.
515
+ def foreach[K, V](m: Tree[K, V]) { action: (K, V) => Unit }: Unit = {
516
+ def go(m: Tree[K, V]): Unit = {
517
+ m match {
518
+ case Tip() => ()
519
+ case Bin(_, k, v, l, r) =>
520
+ go(l)
521
+ action(k, v)
522
+ go(r)
523
+ }
524
+ }
525
+ go(m)
526
+ }
527
+
528
+ /// Create a tree from a list of (key, value) pairs.
529
+ /// If the list contains more than one value for the same key,
530
+ /// only the last value is used in the tree.
531
+ ///
532
+ /// O(N) if the list is sorted by key,
533
+ /// O(N log N) otherwise
534
+ def fromList[K, V](pairs: List[(K, V)], compare: (K, K) => Ordering at {}): Tree[K, V] = {
535
+ pairs match {
536
+ case Nil() => Tip()
537
+ case Cons((k, v), Nil()) => singleton(k, v)
538
+ case Cons((k, v), rest) =>
539
+ // TODO: this function should really, **really** get inlined!
540
+ def notOrdered(k: K, pairs: List[(K, V)]) = {
541
+ pairs match {
542
+ case Nil() => false
543
+ case Cons((k2, _), _) => // k >= k2
544
+ compare(k, k2) match {
545
+ case Less() => false
546
+ case Greater() => true
547
+ case Equal() => true
548
+ }
549
+ }
550
+ }
551
+
552
+ // Naive insertion, used for the worst-case scenario when the list is not sorted by key
553
+ def insertMany(m: Tree[K, V], pairs: List[(K, V)]) = {
554
+ var treeSoFar = m
555
+ pairs.foreach { case (k, v) =>
556
+ treeSoFar = treeSoFar.put(compare, k, v)
557
+ }
558
+ treeSoFar
559
+ }
560
+
561
+ // Returns a triple `(tree, xs, ys)`
562
+ //
563
+ // Invariant: At least one of `xs`, `ys` is empty.
564
+ // Moreover, if `ys` is nonempty, its keys are **not** ordered!
565
+ // Otherwise, all of the seen keys have been ordered so far.
566
+ //
567
+ // TODO: Possibly use a better type to encode the invariant?
568
+ def create(level: Int, pairs: List[(K, V)]): (Tree[K, V], List[(K, V)], List[(K, V)]) = {
569
+ pairs match {
570
+ case Nil() => (Tip(), [], [])
571
+ case Cons((k, v), rest) =>
572
+ if (level == 1) {
573
+ val singleton = Bin(1, k, v, Tip(), Tip())
574
+ if (notOrdered(k, rest)) {
575
+ (singleton, [], rest)
576
+ } else {
577
+ (singleton, rest, [])
578
+ }
579
+ } else {
580
+ val res = create(level.bitwiseShr(1), pairs)
581
+ res match {
582
+ case (_, Nil(), _) => res
583
+ case (l, Cons((k2, v2), Nil()), zs) => (l.putMax(k2, v2), [], zs)
584
+ case (l, Cons((k2, v2), rest2), _) =>
585
+ val xs = Cons((k2, v2), rest2) // @-pattern
586
+
587
+ if (notOrdered(k2, rest2)) { (l, [], xs) }
588
+ else {
589
+ val (r, zs, ws) = create(level.bitwiseShr(1), rest2);
590
+ (link(k2, v2, l, r), zs, ws)
591
+ }
592
+ }
593
+ }
594
+ }
595
+ }
596
+
597
+ def go(level: Int, m: Tree[K, V], pairs: List[(K, V)]): Tree[K, V] = {
598
+ pairs match {
599
+ case Nil() => m
600
+ case Cons((k, v), Nil()) => m.putMax(k, v)
601
+ case Cons((k, v), rest) =>
602
+ if (notOrdered(k, rest)) { insertMany(m, pairs) }
603
+ else {
604
+ val l = m; // m is the left subtree here
605
+ val cr = create(level, rest)
606
+ cr match {
607
+ case (r, xs, Nil()) => go(level.bitwiseShl(1), link(k, v, l, r), xs)
608
+ case (r, Nil(), ys) => insertMany(link(k, v, l, r), ys)
609
+ case _ => panic("create: go: cannot happen, invariant broken!")
610
+ }
611
+ }
612
+ }
613
+ }
614
+
615
+ if (notOrdered(k, rest)) { insertMany(singleton(k, v), rest) }
616
+ else { go(1, singleton(k, v), rest) }
617
+ }
618
+ }
619
+
620
+ /// Remove a key `k` from a tree `m`.
621
+ /// If `k` is not in `m`, `m` is returned.
622
+ ///
623
+ /// O(log N)
624
+ def delete[K, V](m: Tree[K, V], compare: (K, K) => Ordering at {}, k: K): Tree[K, V] =
625
+ m match {
626
+ case Tip() => Tip()
627
+ case Bin(_, k2, v2, l, r) =>
628
+ compare(k, k2) match {
629
+ case Less() => balance(k2, v2, l.delete(compare, k), r)
630
+ case Greater() => balance(k2, v2, l, r.delete(compare, k))
631
+ case Equal() => glue(l, r)
632
+ }
633
+ }
634
+
635
+ /// Can be used to insert, delete, or update a value.
636
+ /// Law: `get(m.alter(k){f}, k) === f(get(m, k))`
637
+ ///
638
+ /// O(log N)
639
+ def alter[K, V](m: Tree[K, V], compare: (K, K) => Ordering at {}, k: K) { f: Option[V] => Option[V] }: Tree[K, V] =
640
+ m match {
641
+ case Tip() =>
642
+ f(None()) match {
643
+ case None() => Tip()
644
+ case Some(v) => singleton(k, v)
645
+ }
646
+ case Bin(size, k2, v2, l, r) =>
647
+ compare(k, k2) match {
648
+ case Less() => balance(k2, v2, l.alter(compare, k){f}, r)
649
+ case Greater() => balance(k2, v2, l, r.alter(compare, k){f})
650
+ case Equal() =>
651
+ f(Some(v2)) match {
652
+ case Some(v) => Bin(size, k2, v, l, r)
653
+ case None() => glue(l, r)
654
+ }
655
+ }
656
+ }
657
+
658
+ /// Update or delete a value associated with key `k` in tree `m`.
659
+ ///
660
+ /// O(log N)
661
+ def update[K, V](m: Tree[K, V], compare: (K, K) => Ordering at {}, k: K) { f: (K, V) => Option[V] }: Tree[K, V] =
662
+ m match {
663
+ case Tip() => Tip()
664
+ case Bin(size, k2, v2, l, r) =>
665
+ compare(k, k2) match {
666
+ case Less() => balance(k2, v2, l.update(compare, k){f}, r)
667
+ case Greater() => balance(k2, v2, l, r.update(compare, k){f})
668
+ case Equal() =>
669
+ f(k2, v2) match {
670
+ case Some(v) => Bin(size, k2, v, l, r)
671
+ case None() => glue(l, r)
672
+ }
673
+ }
674
+ }
675
+
676
+ /// Get `n`-th (key, value) pair in the tree `m`.
677
+ ///
678
+ /// O(log N)
679
+ def getIndex[K, V](m: Tree[K, V], n: Int): Option[(K, V)] =
680
+ m match {
681
+ case Tip() => None()
682
+ case Bin(size, k, v, l, r) =>
683
+ val sizeL = l.size()
684
+ compareInt(sizeL, n) match {
685
+ case Less() => r.getIndex(n - (sizeL + 1))
686
+ case Greater() => l.getIndex(n)
687
+ case Equal() => Some((k, v))
688
+ }
689
+ }
690
+
691
+ /// Construct a new tree which contains all elements of `m1`
692
+ /// except those where the key is found in `m2`.
693
+ ///
694
+ /// O(???)
695
+ def difference[K, V](m1: Tree[K, V], m2: Tree[K, V], compare: (K, K) => Ordering at {}): Tree[K, V] =
696
+ (m1, m2) match {
697
+ case (Tip(), m2) => Tip()
698
+ case (m1, Tip()) => m1
699
+ case (m1, Bin(_, k, _, l2, r2)) =>
700
+ val (l1, _, r1) = m1.splitLookup(compare, k)
701
+ val leftDiff = l1.difference(l2, compare)
702
+ val rightDiff = r1.difference(r2, compare)
703
+ if ((leftDiff.size() + rightDiff.size()) == m1.size()) { m1 }
704
+ else { link2(leftDiff, rightDiff) }
705
+ }
706
+
707
+ /// Construct a new tree which contains the elements of both `m1` and `m2`.
708
+ /// When a key is associated with a value in both `m1` and `m2`, the new value is determined using the `combine` function.
709
+ ///
710
+ /// O(???)
711
+ def union[K, V](m1: Tree[K, V], m2: Tree[K, V], compare: (K, K) => Ordering at {}) { combine : (K, V, V) => V }: Tree[K, V] = {
712
+ /// Internal function similar to `putWithKey`, but right-biased. Only used here, recursively.
713
+ def putWithKeyR(m: Tree[K, V], k: K, v: V): Tree[K, V] = {
714
+ m match {
715
+ case Tip() => singleton(k, v)
716
+ case Bin(size, k2, v2, l, r) =>
717
+ compare(k, k2) match {
718
+ case Less() => balance(k2, v2, l.putWithKeyR(k, v), r)
719
+ case Greater() => balance(k2, v2, l, r.putWithKeyR(k, v))
720
+ case Equal() => Bin(size, k, combine(k2, v2, v), l, r)
721
+ }
722
+ }
723
+ }
724
+
725
+ (m1, m2) match {
726
+ case (_, Tip()) => m1
727
+ case (_, Bin(_, k, v, Tip(), Tip())) => m1.putWithKeyR(k, v)
728
+ case (Bin(_, k, v, Tip(), Tip()), _) => m2.putWithKey(compare, k, v){combine}
729
+ case (Tip(), _) => m2
730
+ case (Bin(_, k1, v1, l1, r1), _) =>
731
+ val (l2, optMid, r2) = m2.splitLookup(compare, k1)
732
+ val leftUnion = union(l1, l2, compare){combine}
733
+ val rightUnion = union(r1, r2, compare){combine}
734
+ optMid match {
735
+ case None() => link(k1, v1, leftUnion, rightUnion)
736
+ case Some(v2) => link(k1, combine(k1, v1, v2), leftUnion, rightUnion)
737
+ }
738
+ }
739
+ }
740
+
741
+ /// Construct a new tree which combines all elements that are in both `m1` and `m2` using the `combine` function.
742
+ ///
743
+ /// O(???)
744
+ def intersection[K, A, B, C](m1: Tree[K, A], m2: Tree[K, B], compare: (K, K) => Ordering at {}) { combine: (K, A, B) => C }: Tree[K, C] =
745
+ (m1, m2) match {
746
+ case (Tip(), _) => Tip()
747
+ case (_, Tip()) => Tip()
748
+ case (Bin(_, k, v1, l1, r1), _) =>
749
+ val (l2, mid, r2) = m2.splitLookup(compare, k)
750
+ val left = l1.intersection(l2, compare) { combine }
751
+ val right = r1.intersection(r2, compare) { combine }
752
+ mid match {
753
+ case Some(v2) => link(k, combine(k, v1, v2), left, right)
754
+ case None() => link2(left, right)
755
+ }
756
+ }
757
+
758
+ // -------------
759
+ // Internal
760
+
761
+ val ratio = 2
762
+ val delta = 3
763
+
764
+ def bin[K, V](k: K, v: V, l: Tree[K, V], r: Tree[K, V]): Tree[K, V] = {
765
+ Bin(l.size() + r.size() + 1, k, v, l, r)
766
+ }
767
+
768
+ def balance[K, V](k: K, v: V, l: Tree[K, V], r: Tree[K, V]): Tree[K, V] = {
769
+ /*
770
+ k1->v1
771
+ / \
772
+ t1 m k2->v2
773
+ = / \
774
+ k2->v2 ~> k1->v1 t3
775
+ / \ / \
776
+ t2 t3 t1 t2
777
+ */
778
+ def singleL[A, B](k1: A, v1: B, t1: Tree[A, B], m: Tree[A, B]): Tree[A, B] = {
779
+ m match {
780
+ case Bin(_, k2, v2, t2, t3) => bin(k2, v2, bin(k1, v1, t1, t2), t3)
781
+ case _ => panic("impossible: singleL: Tip")
782
+ }
783
+ }
784
+
785
+ /*
786
+ k1->v1
787
+ / \
788
+ m t3 k2->v2
789
+ = / \
790
+ k2->v2 ~> t1 k1->v1
791
+ / \ / / \
792
+ t1 t2 t1 t2 t3
793
+ */
794
+ def singleR[A, B](k1: A, v1: B, m: Tree[A, B], t3: Tree[A, B]): Tree[A, B] = {
795
+ m match {
796
+ case Bin(_, k2, v2, t1, t2) => bin(k2, v2, t1, bin(k1, v1, t2, t3))
797
+ case _ => panic("impossible: singleR: Tip")
798
+ }
799
+ }
800
+
801
+ /*
802
+ k1->v1 k3->v3
803
+ / \ / \
804
+ t1 m k1->v1 k2->v2
805
+ = / \ / \
806
+ k2->v2 ~> t1 t2 t3 t4
807
+ / \
808
+ k3->v3 t4
809
+ / \
810
+ t2 t3
811
+ */
812
+ def doubleL[A, B](k1: A, v1: B, t1: Tree[A, B], m: Tree[A, B]): Tree[A, B] = {
813
+ m match {
814
+ case Bin(_, k2, v2, Bin(_, k3, v3, t2, t3), t4) =>
815
+ bin(k3, v3, bin(k1, v1, t1, t2), bin(k2, v2, t3, t4))
816
+ case _ => panic("impossible: doubleL: Tip")
817
+ }
818
+ }
819
+
820
+ /*
821
+ k1->v1 k3->v3
822
+ / \ / \
823
+ m t4 k2->v2 k1->v1
824
+ = / \ / \
825
+ k2->v2 ~> t1 t2 t3 t4
826
+ / \
827
+ t1 k3->v3
828
+ / \
829
+ t2 t3
830
+ */
831
+ def doubleR[A, B](k1: A, v1: B, m: Tree[A, B], t4: Tree[A, B]): Tree[A, B] = {
832
+ m match {
833
+ case Bin(_, k2, v2, t1, Bin(_, k3, v3, t2, t3)) =>
834
+ bin(k3, v3, bin(k2, v2, t1, t2), bin(k1, v1, t3, t4))
835
+ case _ =>
836
+ panic("impossible: doubleR: Tip")
837
+ }
838
+ }
839
+
840
+ def rotateL[A, B](k: A, v: B, l: Tree[A, B], r: Tree[A, B]): Tree[A, B] = {
841
+ r match {
842
+ case Bin(_, _, _, rl, rr) and (rl.size() < ratio * rr.size()) => singleL(k, v, l, r)
843
+ case _ => doubleL(k, v, l, r)
844
+ }
845
+ }
846
+ def rotateR[A, B](k: A, v: B, l: Tree[A, B], r: Tree[A, B]): Tree[A, B] = {
847
+ l match {
848
+ case Bin(_, _, _, ll, lr) and (lr.size() < ratio * ll.size()) => singleR(k, v, l, r)
849
+ case _ => doubleR(k, v, l, r)
850
+ }
851
+ }
852
+
853
+ val sizeL = l.size()
854
+ val sizeR = r.size()
855
+ val sizeCombined = sizeL + sizeR + 1
856
+
857
+ if ((sizeL + sizeR) <= 1) { Bin(sizeCombined, k, v, l, r) }
858
+ else if (sizeR > (delta * sizeL)) { rotateL(k, v, l, r) }
859
+ else if (sizeL > (delta * sizeR)) { rotateR(k, v, l, r) }
860
+ else { Bin(sizeCombined, k, v, l, r)}
861
+ }
862
+
863
+ record MaxView[K, V](k: K, v: V, m: Tree[K, V])
864
+ record MinView[K, V](k: K, v: V, m: Tree[K, V])
865
+
866
+ def maxViewSure[K, V](k: K, v: V, l: Tree[K, V], r: Tree[K, V]): MaxView[K, V] =
867
+ (l, r) match {
868
+ case (l, Tip()) => MaxView(k, v, l)
869
+ case (l, Bin(_, kr, vr, rl, rr)) =>
870
+ val MaxView(km, vm, r2) = maxViewSure(kr, vr, rl, rr)
871
+ MaxView(km, vm, balance(k, v, l, r2))
872
+ }
873
+
874
+ def minViewSure[K, V](k: K, v: V, l: Tree[K, V], r: Tree[K, V]): MinView[K, V] =
875
+ (l, r) match {
876
+ case (Tip(), r) => MinView(k, v, r)
877
+ case (Bin(_, kl, vl, ll, lr), r) =>
878
+ val MinView(km, vm, l2) = minViewSure(kl, vl, ll, lr)
879
+ MinView(km, vm, balance(k, v, l2, r))
880
+ }
881
+
882
+ /// Internal: Glues two balanced trees (with respect to each other) together.
883
+ def glue[K, V](l: Tree[K, V], r: Tree[K, V]): Tree[K, V] =
884
+ (l, r) match {
885
+ case (Tip(), r) => r
886
+ case (l, Tip()) => l
887
+ case (Bin(sizeL, kl, vl, ll, lr), Bin(sizeR, kr, vr, rl, rr)) =>
888
+ if (sizeL > sizeR) {
889
+ val MaxView(km, m, l2) = maxViewSure(kl, vl, ll, lr)
890
+ balance(km, m, l2, r)
891
+ } else {
892
+ val MinView(km, m, r2) = minViewSure(kr, vr, rl, rr)
893
+ balance(km, m, l, r2)
894
+ }
895
+ }
896
+
897
+ def splitLookup[K, V](m: Tree[K, V], compare: (K, K) => Ordering at {}, k: K): (Tree[K, V], Option[V], Tree[K, V]) =
898
+ m match {
899
+ case Tip() => (Tip(), None(), Tip())
900
+ case Bin(_, k2, v2, l, r) =>
901
+ compare(k, k2) match {
902
+ case Less() =>
903
+ val (lessThan, mid, greaterThan) = l.splitLookup(compare, k);
904
+ (lessThan, mid, link(k2, v2, greaterThan, r))
905
+ case Greater() =>
906
+ val (lessThan, mid, greaterThan) = r.splitLookup(compare, k);
907
+ (link(k2, v2, l, lessThan), mid, greaterThan)
908
+ case Equal() => (l, Some(v2), r)
909
+ }
910
+ }
911
+
912
+ def link[K, V](k: K, v: V, l: Tree[K, V], r: Tree[K, V]): Tree[K, V] = {
913
+ (l, r) match {
914
+ case (Tip(), r) => r.putMin(k, v)
915
+ case (l, Tip()) => l.putMax(k, v)
916
+ case (Bin(sizeL, kl, vl, ll, lr), Bin(sizeR, kr, vr, rl, rr)) =>
917
+ if ((delta * sizeL) < sizeR) { balance(kr, vr, link(k, v, l, rl), rr) }
918
+ else if ((delta * sizeR) < sizeL) { balance(kl, vl, ll, link(k, v, lr, r)) }
919
+ else { bin(k, v, l, r) }
920
+ }
921
+ }
922
+
923
+ /// Internal: merge two trees
924
+ def link2[K, V](l: Tree[K, V], r: Tree[K, V]): Tree[K, V] =
925
+ (l, r) match {
926
+ case (Tip(), r) => r
927
+ case (l, Tip()) => l
928
+ case (Bin(sizeL, kl, vl, ll, lr), Bin(sizeR, kr, vr, rl, rr)) =>
929
+ if ((delta * sizeL) < sizeR) { balance(kr, vr, link2(l, lr), rr) }
930
+ else if ((delta * sizeR) < sizeL) { balance(kl, vl, ll, link2(lr, r)) }
931
+ else { glue(l, r) }
932
+ }
933
+
934
+ def putMin[K, V](m: Tree[K, V], k: K, v: V): Tree[K, V] =
935
+ m match {
936
+ case Tip() => singleton(k, v)
937
+ case Bin(_, k2, v2, l, r) =>
938
+ balance(k2, v2, l.putMin(k, v), r)
939
+ }
940
+
941
+ def putMax[K, V](m: Tree[K, V], k: K, v: V): Tree[K, V] =
942
+ m match {
943
+ case Tip() => singleton(k, v)
944
+ case Bin(_, k2, v2, l, r) =>
945
+ balance(k2, v2, l, r.putMax(k, v))
946
+ }
947
+
948
+ // Section: for tests and invariants:
949
+
950
+ /// Check if a tree `m` is balanced.
951
+ def isBalanced[K, V](m: Tree[K, V]): Bool =
952
+ m match {
953
+ case Tip() => true
954
+ case Bin(_, _, _, l, r) =>
955
+ val bothSmall = l.size() + r.size() <= 1
956
+ val leftSmallEnough = l.size() <= delta * r.size()
957
+ val rightSmallEnough = r.size() <= delta * l.size()
958
+ (bothSmall || (leftSmallEnough && rightSmallEnough)) && isBalanced(l) && isBalanced(r)
959
+ }
960
+
961
+ // Section: prettyprinting for trees:
962
+
963
+ /// Works only on the backends that support `genericShow` (JavaScript)!
964
+ def prettyTree[K, V](m: Tree[K, V]): String = {
965
+ // Helper function to recursively build the string representation of the tree
966
+ def go(t: Tree[K, V], prefix: String, isTail: Bool): String = {
967
+ t match {
968
+ case Tip() => ""
969
+ case Bin(_, k, v, l, r) =>
970
+ val pair = k.genericShow ++ " → " ++ v.genericShow
971
+ val currentLine = prefix ++ (if (isTail) "└── " else "├── ") ++ pair ++ "\n"
972
+
973
+ val newPrefix = prefix ++ (if (isTail) " " else "│ ")
974
+ val leftStr = go(l, newPrefix, false)
975
+ val rightStr = go(r, newPrefix, true)
976
+
977
+ currentLine ++ leftStr ++ rightStr
978
+ }
979
+ }
980
+
981
+ // Start the recursion with the initial tree, an empty prefix, and true for the root being the tail
982
+ go(m, "", true)
983
+ }
984
+
985
+ def prettyPairs[K, V](list: List[(K, V)]) { showLeft: K => String } { showRight: V => String }: String = {
986
+ val res: String =
987
+ list.map { case (k, v) => showLeft(k) ++ " → " ++ showRight(v) }
988
+ .join(", ")
989
+
990
+ "[" ++ res ++ "]"
991
+ }
992
+ }