|
| 1 | +package kategory |
| 2 | + |
| 3 | +import java.util.* |
| 4 | + |
| 5 | +@higherkind |
| 6 | +data class SortedMapKW<A: Comparable<A>, B>(val map: SortedMap<A, B>) : SortedMapKWKind<A, B>, SortedMap<A, B> by map { |
| 7 | + |
| 8 | + fun <C> map(f: (B) -> C): SortedMapKW<A, C> = |
| 9 | + this.map.map { it.key to f(it.value) }.toMap().toSortedMap().k() |
| 10 | + |
| 11 | + fun <C, Z> map2(fc: SortedMapKW<A, C>, f: (B, C) -> Z): SortedMapKW<A, Z> = |
| 12 | + if (fc.isEmpty()) sortedMapOf<A, Z>().k() |
| 13 | + else this.map.flatMap { (a, b) -> |
| 14 | + fc.getOption(a).map { Tuple2(a, f(b, it)) }.k().asIterable() |
| 15 | + }.k() |
| 16 | + |
| 17 | + fun <C, Z> map2Eval(fc: Eval<SortedMapKW<A, C>>, f: (B, C) -> Z): Eval<SortedMapKW<A, Z>> = |
| 18 | + if (fc.isEmpty()) Eval.now(sortedMapOf<A, Z>().k()) |
| 19 | + else fc.map { c -> this.map2(c, f) } |
| 20 | + |
| 21 | + fun <C> ap(ff: SortedMapKW<A, (B) -> C>): SortedMapKW<A, C> = |
| 22 | + ff.flatMap { this.map(it) } |
| 23 | + |
| 24 | + fun <C, Z> ap2(f: SortedMapKW<A, (B, C) -> Z>, fc: SortedMapKW<A, C>): SortedMap<A, Z> = |
| 25 | + f.map.flatMap { (k, f) -> |
| 26 | + this.flatMap { a -> fc.flatMap { c -> sortedMapOf(k to f(a, c)).k() } } |
| 27 | + .getOption(k).map { Tuple2(k, it) }.k().asIterable() |
| 28 | + }.k() |
| 29 | + |
| 30 | + fun <C> flatMap(f: (B) -> SortedMapKW<A, C>): SortedMapKW<A, C> = |
| 31 | + this.map.flatMap { (k, v) -> |
| 32 | + f(v).getOption(k).map { Tuple2(k, it) }.k().asIterable() |
| 33 | + }.k() |
| 34 | + |
| 35 | + fun <C> foldR(c: Eval<C>, f: (B, Eval<C>) -> Eval<C>): Eval<C> = |
| 36 | + this.map.values.iterator().iterateRight(c)(f) |
| 37 | + |
| 38 | + fun <C> foldL(c: C, f: (C, B) -> C): C = this.map.values.fold(c, f) |
| 39 | + |
| 40 | + fun <C> foldLeft(c: SortedMapKW<A, C>, f: (SortedMapKW<A, C>, Tuple2<A, B>) -> SortedMapKW<A, C>): SortedMapKW<A, C> = |
| 41 | + this.map.foldLeft(c) { m: SortedMap<A, C>, (a, b) -> f(m.k(), Tuple2(a, b)) }.k() |
| 42 | + |
| 43 | + fun <G, C> traverse(f: (B) -> HK<G, C>, GA: Applicative<G>): HK<G, SortedMapKW<A, C>> = |
| 44 | + Foldable.iterateRight(this.map.iterator(), Eval.always { GA.pure(sortedMapOf<A, C>().k()) })({ |
| 45 | + kv, lbuf -> |
| 46 | + GA.map2Eval(f(kv.value), lbuf) { (mapOf(kv.key to it.a).k() + it.b).toSortedMap().k() } |
| 47 | + }).value() |
| 48 | + |
| 49 | + companion object |
| 50 | +} |
| 51 | + |
| 52 | +fun <A: Comparable<A>, B> SortedMap<A, B>.k(): SortedMapKW<A, B> = SortedMapKW(this) |
| 53 | + |
| 54 | +fun <A: Comparable<A>, B> Option<Tuple2<A, B>>.k(): SortedMapKW<A, B> = this.fold( |
| 55 | + { sortedMapOf<A, B>().k() }, |
| 56 | + { mapEntry -> sortedMapOf<A, B>(mapEntry.a to mapEntry.b).k() } |
| 57 | +) |
| 58 | + |
| 59 | +fun <A: Comparable<A>, B> List<Map.Entry<A, B>>.k(): SortedMapKW<A, B> = |
| 60 | + this.map { it.key to it.value }.toMap().toSortedMap().k() |
| 61 | + |
| 62 | +fun <A, B> SortedMap<A, B>.getOption(k: A): Option<B> = Option.fromNullable(this[k]) |
| 63 | + |
| 64 | +fun <A: Comparable<A>, B> SortedMapKW<A, B>.updated(k: A, value: B): SortedMapKW<A, B> { |
| 65 | + val sortedMutableMap = this.toSortedMap() |
| 66 | + sortedMutableMap.put(k, value) |
| 67 | + |
| 68 | + return sortedMutableMap.k() |
| 69 | +} |
| 70 | + |
| 71 | +fun <A, B, C> SortedMap<A, B>.foldLeft(b: SortedMap<A, C>, f: (SortedMap<A, C>, Map.Entry<A, B>) -> SortedMap<A, C>): SortedMap<A, C> { |
| 72 | + var result = b |
| 73 | + this.forEach { result = f(result, it) } |
| 74 | + return result |
| 75 | +} |
| 76 | + |
| 77 | +fun <A: Comparable<A>, B, C> SortedMap<A, B>.foldRight(b: SortedMap<A, C>, f: (Map.Entry<A, B>, SortedMap<A, C>) -> SortedMap<A, C>): SortedMap<A, C> = |
| 78 | + this.entries.reversed().k().map.foldLeft(b) { x: SortedMap<A, C>, y -> f(y, x) } |
0 commit comments