From 5872348c366c70e76bee6b9dfbe43671a694ad4c Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Wed, 3 Mar 2021 16:22:40 +0100 Subject: [PATCH 1/2] Deprecate old mapN and expose new mapN --- .../src/main/kotlin/arrow/core/List.kt | 119 ++++++++++ .../src/main/kotlin/arrow/core/ListK.kt | 37 +++ .../src/main/kotlin/arrow/core/MapK.kt | 43 +++- .../src/main/kotlin/arrow/core/Nullable.kt | 36 --- .../src/main/kotlin/arrow/core/Sequence.kt | 198 +++++++++++++++- .../src/main/kotlin/arrow/core/SequenceK.kt | 38 ++++ .../src/main/kotlin/arrow/core/map.kt | 215 ++++++++++++++++++ .../test/kotlin/arrow/core/NullableTest.kt | 36 +-- 8 files changed, 661 insertions(+), 61 deletions(-) diff --git a/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/List.kt b/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/List.kt index b7e9658c662..5680cea996f 100644 --- a/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/List.kt +++ b/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/List.kt @@ -4,6 +4,125 @@ import arrow.typeclasses.Monoid import arrow.typeclasses.Semigroup import kotlin.collections.plus as _plus +inline fun mapN( + b: Iterable, + c: Iterable, + map: (B, C) -> D +): List = + mapN(b, c, unit, unit, unit, unit, unit, unit, unit, unit) { b, c, _, _, _, _, _, _, _, _ -> map(b, c) } + +inline fun mapN( + b: Iterable, + c: Iterable, + d: Iterable, + map: (B, C, D) -> E +): List = + mapN(b, c, d, unit, unit, unit, unit, unit, unit, unit) { b, c, d, _, _, _, _, _, _, _ -> map(b, c, d) } + +inline fun mapN( + b: Iterable, + c: Iterable, + d: Iterable, + e: Iterable, + map: (B, C, D, E) -> F +): List = + mapN(b, c, d, e, unit, unit, unit, unit, unit, unit) { b, c, d, e, _, _, _, _, _, _ -> map(b, c, d, e) } + +inline fun mapN( + b: Iterable, + c: Iterable, + d: Iterable, + e: Iterable, + f: Iterable, + map: (B, C, D, E, F) -> G +): List = + mapN(b, c, d, e, f, unit, unit, unit, unit, unit) { b, c, d, e, f, _, _, _, _, _ -> map(b, c, d, e, f) } + +inline fun mapN( + b: Iterable, + c: Iterable, + d: Iterable, + e: Iterable, + f: Iterable, + g: Iterable, + map: (B, C, D, E, F, G) -> H +): List = + mapN(b, c, d, e, f, g, unit, unit, unit, unit) { b, c, d, e, f, g, _, _, _, _ -> map(b, c, d, e, f, g) } + +inline fun mapN( + b: Iterable, + c: Iterable, + d: Iterable, + e: Iterable, + f: Iterable, + g: Iterable, + h: Iterable, + map: (B, C, D, E, F, G, H) -> I +): List = + mapN(b, c, d, e, f, g, h, unit, unit, unit) { b, c, d, e, f, g, h, _, _, _ -> map(b, c, d, e, f, g, h) } + +inline fun mapN( + b: Iterable, + c: Iterable, + d: Iterable, + e: Iterable, + f: Iterable, + g: Iterable, + h: Iterable, + i: Iterable, + map: (B, C, D, E, F, G, H, I) -> J +): List = + mapN(b, c, d, e, f, g, h, i, unit, unit) { b, c, d, e, f, g, h, i, _, _ -> map(b, c, d, e, f, g, h, i) } + +inline fun mapN( + b: Iterable, + c: Iterable, + d: Iterable, + e: Iterable, + f: Iterable, + g: Iterable, + h: Iterable, + i: Iterable, + j: Iterable, + map: (B, C, D, E, F, G, H, I, J) -> K +): List = + mapN(b, c, d, e, f, g, h, i, j, unit) { b, c, d, e, f, g, h, i, j, _ -> map(b, c, d, e, f, g, h, i, j) } + +inline fun mapN( + b: Iterable, + c: Iterable, + d: Iterable, + e: Iterable, + f: Iterable, + g: Iterable, + h: Iterable, + i: Iterable, + j: Iterable, + k: Iterable, + map: (B, C, D, E, F, G, H, I, J, K) -> L +): List = + b.flatMap { bb -> + c.flatMap { cc -> + d.flatMap { dd -> + e.flatMap { ee -> + f.flatMap { ff -> + g.flatMap { gg -> + h.flatMap { hh -> + i.flatMap { ii -> + j.flatMap { jj -> + k.map { kk -> + map(bb, cc, dd, ee, ff, gg, hh, ii, jj, kk) + } + } + } + } + } + } + } + } + } + } + fun Semigroup.Companion.list(): Semigroup> = Monoid.list() diff --git a/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/ListK.kt b/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/ListK.kt index 50766cae34d..1d3438481db 100644 --- a/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/ListK.kt +++ b/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/ListK.kt @@ -1,7 +1,12 @@ package arrow.core +@Deprecated("ListK object is deprecated, and will be removed in 1.0.0") object ListK { + @Deprecated( + "mapN for Iterable has become a top-level function.", + ReplaceWith("mapN(b, c, map)", "arrow.core.mapN") + ) inline fun mapN( b: Iterable, c: Iterable, @@ -9,6 +14,10 @@ object ListK { ): List = mapN(b, c, unit, unit, unit, unit, unit, unit, unit, unit) { b, c, _, _, _, _, _, _, _, _ -> map(b, c) } + @Deprecated( + "mapN for Iterable has become a top-level function.", + ReplaceWith("mapN(b, c, d, map)", "arrow.core.mapN") + ) inline fun mapN( b: Iterable, c: Iterable, @@ -17,6 +26,10 @@ object ListK { ): List = mapN(b, c, d, unit, unit, unit, unit, unit, unit, unit) { b, c, d, _, _, _, _, _, _, _ -> map(b, c, d) } + @Deprecated( + "mapN for Iterable has become a top-level function.", + ReplaceWith("mapN(b, c, d, e, map)", "arrow.core.mapN") + ) inline fun mapN( b: Iterable, c: Iterable, @@ -26,6 +39,10 @@ object ListK { ): List = mapN(b, c, d, e, unit, unit, unit, unit, unit, unit) { b, c, d, e, _, _, _, _, _, _ -> map(b, c, d, e) } + @Deprecated( + "mapN for Iterable has become a top-level function.", + ReplaceWith("mapN(b, c, d, e, f, map)", "arrow.core.mapN") + ) inline fun mapN( b: Iterable, c: Iterable, @@ -36,6 +53,10 @@ object ListK { ): List = mapN(b, c, d, e, f, unit, unit, unit, unit, unit) { b, c, d, e, f, _, _, _, _, _ -> map(b, c, d, e, f) } + @Deprecated( + "mapN for Iterable has become a top-level function.", + ReplaceWith("mapN(b, c, d, e, f, g, map)", "arrow.core.mapN") + ) inline fun mapN( b: Iterable, c: Iterable, @@ -47,6 +68,10 @@ object ListK { ): List = mapN(b, c, d, e, f, g, unit, unit, unit, unit) { b, c, d, e, f, g, _, _, _, _ -> map(b, c, d, e, f, g) } + @Deprecated( + "mapN for Iterable has become a top-level function.", + ReplaceWith("mapN(b, c, d, e, f, g, h, map)", "arrow.core.mapN") + ) inline fun mapN( b: Iterable, c: Iterable, @@ -59,6 +84,10 @@ object ListK { ): List = mapN(b, c, d, e, f, g, h, unit, unit, unit) { b, c, d, e, f, g, h, _, _, _ -> map(b, c, d, e, f, g, h) } + @Deprecated( + "mapN for Iterable has become a top-level function.", + ReplaceWith("mapN(b, c, d, e, f, g, h, i, map)", "arrow.core.mapN") + ) inline fun mapN( b: Iterable, c: Iterable, @@ -72,6 +101,10 @@ object ListK { ): List = mapN(b, c, d, e, f, g, h, i, unit, unit) { b, c, d, e, f, g, h, i, _, _ -> map(b, c, d, e, f, g, h, i) } + @Deprecated( + "mapN for Iterable has become a top-level function.", + ReplaceWith("mapN(b, c, d, e, f, g, h, i, j, map)", "arrow.core.mapN") + ) inline fun mapN( b: Iterable, c: Iterable, @@ -86,6 +119,10 @@ object ListK { ): List = mapN(b, c, d, e, f, g, h, i, j, unit) { b, c, d, e, f, g, h, i, j, _ -> map(b, c, d, e, f, g, h, i, j) } + @Deprecated( + "mapN for Iterable has become a top-level function.", + ReplaceWith("mapN(b, c, d, e, f, g, h, i, j, k, map)", "arrow.core.mapN") + ) inline fun mapN( b: Iterable, c: Iterable, diff --git a/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/MapK.kt b/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/MapK.kt index 83fca15c09e..edea2e91f75 100644 --- a/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/MapK.kt +++ b/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/MapK.kt @@ -1,7 +1,12 @@ package arrow.core +@Deprecated("MapK object is deprecated, and will be removed in 1.0.0") object MapK { + @Deprecated( + "mapN for Map has become a top-level function.", + ReplaceWith("mapN(b, c, map)", "arrow.core.mapN") + ) inline fun mapN( b: Map, c: Map, @@ -22,6 +27,10 @@ object MapK { map(key, bb, cc) } + @Deprecated( + "mapN for Map has become a top-level function.", + ReplaceWith("mapN(b, c, d, map)", "arrow.core.mapN") + ) inline fun mapN( b: Map, c: Map, @@ -43,6 +52,10 @@ object MapK { map(key, bb, cc, dd) } + @Deprecated( + "mapN for Map has become a top-level function.", + ReplaceWith("mapN(b, c, d, e, map)", "arrow.core.mapN") + ) inline fun mapN( b: Map, c: Map, @@ -65,6 +78,10 @@ object MapK { map(key, bb, cc, dd, ee) } + @Deprecated( + "mapN for Map has become a top-level function.", + ReplaceWith("mapN(b, c, d, e, f, map)", "arrow.core.mapN") + ) inline fun mapN( b: Map, c: Map, @@ -88,6 +105,10 @@ object MapK { map(key, bb, cc, dd, ee, ff) } + @Deprecated( + "mapN for Map has become a top-level function.", + ReplaceWith("mapN(b, c, d, e, f, g, map)", "arrow.core.mapN") + ) inline fun mapN( b: Map, c: Map, @@ -112,6 +133,10 @@ object MapK { map(key, bb, cc, dd, ee, ff, gg) } + @Deprecated( + "mapN for Map has become a top-level function.", + ReplaceWith("mapN(b, c, d, e, f, g, h, map)", "arrow.core.mapN") + ) inline fun mapN( b: Map, c: Map, @@ -137,6 +162,10 @@ object MapK { map(key, bb, cc, dd, ee, ff, gg, hh) } + @Deprecated( + "mapN for Map has become a top-level function.", + ReplaceWith("mapN(b, c, d, e, f, g, h, i, map)", "arrow.core.mapN") + ) inline fun mapN( b: Map, c: Map, @@ -163,6 +192,10 @@ object MapK { map(key, bb, cc, dd, ee, ff, gg, hh, ii) } + @Deprecated( + "mapN for Map has become a top-level function.", + ReplaceWith("mapN(b, c, d, e, f, g, h, i, j, map)", "arrow.core.mapN") + ) inline fun mapN( b: Map, c: Map, @@ -179,6 +212,10 @@ object MapK { map(key, bb, cc, dd, ee, ff, gg, hh, ii, jj) } + @Deprecated( + "mapN for Map has become a top-level function.", + ReplaceWith("mapN(b, c, d, e, f, g, h, i, j, k, map)", "arrow.core.mapN") + ) inline fun mapN( b: Map, c: Map, @@ -211,9 +248,3 @@ object MapK { return destination } } - -internal fun Pair?.asIterable(): Iterable> = - when (this) { - null -> emptyList() - else -> listOf(this) - } diff --git a/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/Nullable.kt b/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/Nullable.kt index 68fb473a696..93729c6e765 100644 --- a/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/Nullable.kt +++ b/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/Nullable.kt @@ -49,39 +49,3 @@ object Nullable { } } } - -@Deprecated("Top-level mapN function for A? conflicts with other types such as List and Map", ReplaceWith("Nullable.mapN(a, fn", "arrow.core.mapN")) -inline fun mapN(a: A?, fn: (A) -> R): R? = - Nullable.mapN(a, fn) - -@Deprecated("Top-level mapN function for A? conflicts with other types such as List and Map", ReplaceWith("Nullable.mapN(a, b, fn", "arrow.core.mapN")) -inline fun mapN(a: A?, b: B?, fn: (A, B) -> R): R? = - Nullable.mapN(a, b, fn) - -@Deprecated("Top-level mapN function for A? conflicts with other types such as List and Map", ReplaceWith("Nullable.mapN(a, b, c, fn", "arrow.core.mapN")) -inline fun mapN(a: A?, b: B?, c: C?, fn: (A, B, C) -> R): R? = - Nullable.mapN(a, b, c, fn) - -@Deprecated("Top-level mapN function for A? conflicts with other types such as List and Map", ReplaceWith("Nullable.mapN(a, b, c, d, fn", "arrow.core.mapN")) -inline fun mapN(a: A?, b: B?, c: C?, d: D?, fn: (A, B, C, D) -> R): R? = - Nullable.mapN(a, b, c, d, fn) - -@Deprecated("Top-level mapN function for A? conflicts with other types such as List and Map", ReplaceWith("Nullable.mapN(a, b, c, d, e, fn", "arrow.core.mapN")) -inline fun mapN(a: A?, b: B?, c: C?, d: D?, e: E?, fn: (A, B, C, D, E) -> R): R? = - Nullable.mapN(a, b, c, d, e, fn) - -@Deprecated("Top-level mapN function for A? conflicts with other types such as List and Map", ReplaceWith("Nullable.mapN(a, b, c, d, e, f, fn", "arrow.core.mapN")) -inline fun mapN(a: A?, b: B?, c: C?, d: D?, e: E?, f: F?, fn: (A, B, C, D, E, F) -> R): R? = - Nullable.mapN(a, b, c, d, e, f, fn) - -@Deprecated("Top-level mapN function for A? conflicts with other types such as List and Map", ReplaceWith("Nullable.mapN(a, b, c, d, e, f, g, fn", "arrow.core.mapN")) -inline fun mapN(a: A?, b: B?, c: C?, d: D?, e: E?, f: F?, g: G?, fn: (A, B, C, D, E, F, G) -> R): R? = - Nullable.mapN(a, b, c, d, e, f, g, fn) - -@Deprecated("Top-level mapN function for A? conflicts with other types such as List and Map", ReplaceWith("Nullable.mapN(a, b, c, d, e, f, g, h, fn", "arrow.core.mapN")) -inline fun mapN(a: A?, b: B?, c: C?, d: D?, e: E?, f: F?, g: G?, h: H?, fn: (A, B, C, D, E, F, G, H) -> R): R? = - Nullable.mapN(a, b, c, d, e, f, g, h, fn) - -@Deprecated("Top-level mapN function for A? conflicts with other types such as List and Map", ReplaceWith("Nullable.mapN(a, b, c, d, e, f, g, h, i, fn", "arrow.core.mapN")) -inline fun mapN(a: A?, b: B?, c: C?, d: D?, e: E?, f: F?, g: G?, h: H?, i: I?, fn: (A, B, C, D, E, F, G, H, I) -> R): R? = - Nullable.mapN(a, b, c, d, e, f, g, h, i, fn) diff --git a/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/Sequence.kt b/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/Sequence.kt index 2610baa6ec4..d7dcc20639b 100644 --- a/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/Sequence.kt +++ b/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/Sequence.kt @@ -3,6 +3,202 @@ package arrow.core import arrow.typeclasses.Monoid import arrow.typeclasses.Semigroup +fun mapN( + b: Sequence, + c: Sequence, + map: (B, C) -> D +): Sequence = + mapN( + b, + c, + sequenceOf(Unit), + sequenceOf(Unit), + sequenceOf(Unit), + sequenceOf(Unit), + sequenceOf(Unit), + sequenceOf(Unit), + sequenceOf(Unit), + sequenceOf(Unit) + ) { b, c, _, _, _, _, _, _, _, _ -> map(b, c) } + +fun mapN( + b: Sequence, + c: Sequence, + d: Sequence, + map: (B, C, D) -> E +): Sequence = + mapN( + b, + c, + d, + sequenceOf(Unit), + sequenceOf(Unit), + sequenceOf(Unit), + sequenceOf(Unit), + sequenceOf(Unit), + sequenceOf(Unit), + sequenceOf(Unit) + ) { b, c, d, _, _, _, _, _, _, _ -> map(b, c, d) } + +fun mapN( + b: Sequence, + c: Sequence, + d: Sequence, + e: Sequence, + map: (B, C, D, E) -> F +): Sequence = + mapN( + b, + c, + d, + e, + sequenceOf(Unit), + sequenceOf(Unit), + sequenceOf(Unit), + sequenceOf(Unit), + sequenceOf(Unit), + sequenceOf(Unit) + ) { b, c, d, e, _, _, _, _, _, _ -> map(b, c, d, e) } + +fun mapN( + b: Sequence, + c: Sequence, + d: Sequence, + e: Sequence, + f: Sequence, + map: (B, C, D, E, F) -> G +): Sequence = + mapN( + b, + c, + d, + e, + f, + sequenceOf(Unit), + sequenceOf(Unit), + sequenceOf(Unit), + sequenceOf(Unit), + sequenceOf(Unit) + ) { b, c, d, e, f, _, _, _, _, _ -> map(b, c, d, e, f) } + +fun mapN( + b: Sequence, + c: Sequence, + d: Sequence, + e: Sequence, + f: Sequence, + g: Sequence, + map: (B, C, D, E, F, G) -> H +): Sequence = + mapN( + b, + c, + d, + e, + f, + g, + sequenceOf(Unit), + sequenceOf(Unit), + sequenceOf(Unit), + sequenceOf(Unit) + ) { b, c, d, e, f, g, _, _, _, _ -> map(b, c, d, e, f, g) } + +fun mapN( + b: Sequence, + c: Sequence, + d: Sequence, + e: Sequence, + f: Sequence, + g: Sequence, + h: Sequence, + map: (B, C, D, E, F, G, H) -> I +): Sequence = + mapN( + b, + c, + d, + e, + f, + g, + h, + sequenceOf(Unit), + sequenceOf(Unit), + sequenceOf(Unit) + ) { b, c, d, e, f, g, h, _, _, _ -> map(b, c, d, e, f, g, h) } + +fun mapN( + b: Sequence, + c: Sequence, + d: Sequence, + e: Sequence, + f: Sequence, + g: Sequence, + h: Sequence, + i: Sequence, + map: (B, C, D, E, F, G, H, I) -> J +): Sequence = + mapN(b, c, d, e, f, g, h, i, sequenceOf(Unit), sequenceOf(Unit)) { b, c, d, e, f, g, h, i, _, _ -> + map( + b, + c, + d, + e, + f, + g, + h, + i + ) + } + +fun mapN( + b: Sequence, + c: Sequence, + d: Sequence, + e: Sequence, + f: Sequence, + g: Sequence, + h: Sequence, + i: Sequence, + j: Sequence, + map: (B, C, D, E, F, G, H, I, J) -> K +): Sequence = + mapN(b, c, d, e, f, g, h, i, j, sequenceOf(Unit)) { b, c, d, e, f, g, h, i, j, _ -> map(b, c, d, e, f, g, h, i, j) } + +fun mapN( + b: Sequence, + c: Sequence, + d: Sequence, + e: Sequence, + f: Sequence, + g: Sequence, + h: Sequence, + i: Sequence, + j: Sequence, + k: Sequence, + map: (B, C, D, E, F, G, H, I, J, K) -> L +): Sequence = + b.flatMap { bb -> + c.flatMap { cc -> + d.flatMap { dd -> + e.flatMap { ee -> + f.flatMap { ff -> + g.flatMap { gg -> + h.flatMap { hh -> + i.flatMap { ii -> + j.flatMap { jj -> + k.map { kk -> + map(bb, cc, dd, ee, ff, gg, hh, ii, jj, kk) + } + } + } + } + } + } + } + } + } + } + /** * Combines two structures by taking the union of their shapes and combining the elements with the given function. * @@ -337,7 +533,7 @@ fun Sequence.replicate(n: Int): Sequence> = fun Sequence.replicate(n: Int, MA: Monoid): Sequence = if (n <= 0) sequenceOf(MA.empty()) - else SequenceK.mapN(this@replicate, replicate(n - 1, MA)) { a, xs -> MA.run { a + xs } } + else mapN(this@replicate, replicate(n - 1, MA)) { a, xs -> MA.run { a + xs } } /** * Returns a [Sequence] containing the result of applying some transformation `(A, B?) -> C` diff --git a/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/SequenceK.kt b/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/SequenceK.kt index 1f19eacc253..b15167d2e6f 100644 --- a/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/SequenceK.kt +++ b/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/SequenceK.kt @@ -1,6 +1,12 @@ package arrow.core +@Deprecated("SequenceK object is deprecated, and will be removed in 1.0.0") object SequenceK { + + @Deprecated( + "mapN for Sequence has become a top-level function.", + ReplaceWith("mapN(b, c, map)", "arrow.core.mapN") + ) fun mapN( b: Sequence, c: Sequence, @@ -19,6 +25,10 @@ object SequenceK { sequenceOf(Unit) ) { b, c, _, _, _, _, _, _, _, _ -> map(b, c) } + @Deprecated( + "mapN for Sequence has become a top-level function.", + ReplaceWith("mapN(b, c, d, map)", "arrow.core.mapN") + ) fun mapN( b: Sequence, c: Sequence, @@ -38,6 +48,10 @@ object SequenceK { sequenceOf(Unit) ) { b, c, d, _, _, _, _, _, _, _ -> map(b, c, d) } + @Deprecated( + "mapN for Sequence has become a top-level function.", + ReplaceWith("mapN(b, c, d, e, map)", "arrow.core.mapN") + ) fun mapN( b: Sequence, c: Sequence, @@ -58,6 +72,10 @@ object SequenceK { sequenceOf(Unit) ) { b, c, d, e, _, _, _, _, _, _ -> map(b, c, d, e) } + @Deprecated( + "mapN for Sequence has become a top-level function.", + ReplaceWith("mapN(b, c, d, e, f, map)", "arrow.core.mapN") + ) fun mapN( b: Sequence, c: Sequence, @@ -79,6 +97,10 @@ object SequenceK { sequenceOf(Unit) ) { b, c, d, e, f, _, _, _, _, _ -> map(b, c, d, e, f) } + @Deprecated( + "mapN for Sequence has become a top-level function.", + ReplaceWith("mapN(b, c, d, e, f, g, map)", "arrow.core.mapN") + ) fun mapN( b: Sequence, c: Sequence, @@ -101,6 +123,10 @@ object SequenceK { sequenceOf(Unit) ) { b, c, d, e, f, g, _, _, _, _ -> map(b, c, d, e, f, g) } + @Deprecated( + "mapN for Sequence has become a top-level function.", + ReplaceWith("mapN(b, c, d, e, f, g, h, map)", "arrow.core.mapN") + ) fun mapN( b: Sequence, c: Sequence, @@ -124,6 +150,10 @@ object SequenceK { sequenceOf(Unit) ) { b, c, d, e, f, g, h, _, _, _ -> map(b, c, d, e, f, g, h) } + @Deprecated( + "mapN for Sequence has become a top-level function.", + ReplaceWith("mapN(b, c, d, e, f, g, h, i, map)", "arrow.core.mapN") + ) fun mapN( b: Sequence, c: Sequence, @@ -148,6 +178,10 @@ object SequenceK { ) } + @Deprecated( + "mapN for Sequence has become a top-level function.", + ReplaceWith("mapN(b, c, d, e, f, g, h, i, j, map)", "arrow.core.mapN") + ) fun mapN( b: Sequence, c: Sequence, @@ -162,6 +196,10 @@ object SequenceK { ): Sequence = mapN(b, c, d, e, f, g, h, i, j, sequenceOf(Unit)) { b, c, d, e, f, g, h, i, j, _ -> map(b, c, d, e, f, g, h, i, j) } + @Deprecated( + "mapN for Sequence has become a top-level function.", + ReplaceWith("mapN(b, c, d, e, f, g, h, i, j, k, map)", "arrow.core.mapN") + ) fun mapN( b: Sequence, c: Sequence, diff --git a/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/map.kt b/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/map.kt index d638964a170..d807e2632f8 100644 --- a/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/map.kt +++ b/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/map.kt @@ -8,6 +8,215 @@ object MapInstances object SortedMapInstances +inline fun mapN( + b: Map, + c: Map, + map: (Key, B, C) -> D +): Map = + mapN( + b, + c, + emptyMap(), + emptyMap(), + emptyMap(), + emptyMap(), + emptyMap(), + emptyMap(), + emptyMap(), + emptyMap() + ) { key, bb, cc, _, _, _, _, _, _, _, _ -> + map(key, bb, cc) + } + +inline fun mapN( + b: Map, + c: Map, + d: Map, + map: (Key, B, C, D) -> E +): Map = + mapN( + b, + c, + d, + emptyMap(), + emptyMap(), + emptyMap(), + emptyMap(), + emptyMap(), + emptyMap(), + emptyMap() + ) { key, bb, cc, dd, _, _, _, _, _, _, _ -> + map(key, bb, cc, dd) + } + +inline fun mapN( + b: Map, + c: Map, + d: Map, + e: Map, + map: (Key, B, C, D, E) -> F +): Map = + mapN( + b, + c, + d, + e, + emptyMap(), + emptyMap(), + emptyMap(), + emptyMap(), + emptyMap(), + emptyMap() + ) { key, bb, cc, dd, ee, _, _, _, _, _, _ -> + map(key, bb, cc, dd, ee) + } + +inline fun mapN( + b: Map, + c: Map, + d: Map, + e: Map, + f: Map, + map: (Key, B, C, D, E, F) -> G +): Map = + mapN( + b, + c, + d, + e, + f, + emptyMap(), + emptyMap(), + emptyMap(), + emptyMap(), + emptyMap() + ) { key, bb, cc, dd, ee, ff, _, _, _, _, _ -> + map(key, bb, cc, dd, ee, ff) + } + +inline fun mapN( + b: Map, + c: Map, + d: Map, + e: Map, + f: Map, + g: Map, + map: (Key, B, C, D, E, F, G) -> H +): Map = + mapN( + b, + c, + d, + e, + f, + g, + emptyMap(), + emptyMap(), + emptyMap(), + emptyMap() + ) { key, bb, cc, dd, ee, ff, gg, _, _, _, _ -> + map(key, bb, cc, dd, ee, ff, gg) + } + +inline fun mapN( + b: Map, + c: Map, + d: Map, + e: Map, + f: Map, + g: Map, + h: Map, + map: (Key, B, C, D, E, F, G, H) -> I +): Map = + mapN( + b, + c, + d, + e, + f, + g, + h, + emptyMap(), + emptyMap(), + emptyMap() + ) { key, bb, cc, dd, ee, ff, gg, hh, _, _, _ -> + map(key, bb, cc, dd, ee, ff, gg, hh) + } + +inline fun mapN( + b: Map, + c: Map, + d: Map, + e: Map, + f: Map, + g: Map, + h: Map, + i: Map, + map: (Key, B, C, D, E, F, G, H, I) -> J +): Map = + mapN( + b, + c, + d, + e, + f, + g, + h, + i, + emptyMap(), + emptyMap() + ) { key, bb, cc, dd, ee, ff, gg, hh, ii, _, _ -> + map(key, bb, cc, dd, ee, ff, gg, hh, ii) + } + +inline fun mapN( + b: Map, + c: Map, + d: Map, + e: Map, + f: Map, + g: Map, + h: Map, + i: Map, + j: Map, + map: (Key, B, C, D, E, F, G, H, I, J) -> K +): Map = + mapN(b, c, d, e, f, g, h, i, j, emptyMap()) { key, bb, cc, dd, ee, ff, gg, hh, ii, jj, _ -> + map(key, bb, cc, dd, ee, ff, gg, hh, ii, jj) + } + +inline fun mapN( + b: Map, + c: Map, + d: Map, + e: Map, + f: Map, + g: Map, + h: Map, + i: Map, + j: Map, + k: Map, + map: (Key, B, C, D, E, F, G, H, I, J, K) -> L +): Map { + val destination = LinkedHashMap(b.size) + for ((key, bb) in b) { + Nullable.mapN( + c[key], + d[key], + e[key], + f[key], + g[key], + h[key], + i[key], + j[key], + k[key] + ) { cc, dd, ee, ff, gg, hh, ii, jj, kk -> + map(key, bb, cc, dd, ee, ff, gg, hh, ii, jj, kk) + }?.let { l -> destination.put(key, l) } + } + return destination +} + fun Map.flatMap(f: (Map.Entry) -> Map): Map = _flatMap { entry -> f(entry)[entry.key]?.let { Pair(entry.key, it) }.asIterable() @@ -328,3 +537,9 @@ inline fun Map.foldLeft(b: B, f: (B, Map.Entry) -> B): B { this.forEach { result = f(result, it) } return result } + +internal fun Pair?.asIterable(): Iterable> = + when (this) { + null -> emptyList() + else -> listOf(this) + } diff --git a/arrow-libs/core/arrow-core-data/src/test/kotlin/arrow/core/NullableTest.kt b/arrow-libs/core/arrow-core-data/src/test/kotlin/arrow/core/NullableTest.kt index 1b97d307a5b..d6d0841c6f0 100644 --- a/arrow-libs/core/arrow-core-data/src/test/kotlin/arrow/core/NullableTest.kt +++ b/arrow-libs/core/arrow-core-data/src/test/kotlin/arrow/core/NullableTest.kt @@ -12,23 +12,23 @@ import io.kotlintest.specs.StringSpec class NullableTest : StringSpec({ "map1 short circuits if any arg is null" { - mapN(null) { Unit }.shouldBeNull() + Nullable.mapN(null) { Unit }.shouldBeNull() } "map1 performs action when arg is not null" { forAll(Gen.intSmall()) { a -> - mapN(a) { it + 1 } == a + 1 + Nullable.mapN(a) { it + 1 } == a + 1 } } "map2 only performs action when all arguments are not null" { forAll(combGen("a", null, 2)) { (a: String?, b: String?) -> if (listOf(a, b).all { it != null }) { - mapN(a, b, { a, b -> a + b }).let { + Nullable.mapN(a, b, { a, b -> a + b }).let { it == a!! + b!! } } else { - mapN(a, b, { _, _ -> Unit }) == null + Nullable.mapN(a, b, { _, _ -> Unit }) == null } } } @@ -36,11 +36,11 @@ class NullableTest : StringSpec({ "map3 only performs action when all arguments are not null" { forAll(combGen("a", null, 3)) { (a: String?, b: String?, c: String?) -> if (listOf(a, b, c).all { it != null }) { - mapN(a, b, c, { a, b, c -> a + b + c }).let { + Nullable.mapN(a, b, c, { a, b, c -> a + b + c }).let { it == a!! + b!! + c!! } } else { - mapN(a, b, c, { _, _, _ -> Unit }) == null + Nullable.mapN(a, b, c, { _, _, _ -> Unit }) == null } } } @@ -48,11 +48,11 @@ class NullableTest : StringSpec({ "map4 only performs action when all arguments are not null" { forAll(combGen(1, null, 4)) { (a: Int?, b: Int?, c: Int?, d: Int?) -> if (listOf(a, b, c, d).all { it != null }) { - mapN(a, b, c, d, { a, b, c, d -> a + b + c + d }).let { + Nullable.mapN(a, b, c, d, { a, b, c, d -> a + b + c + d }).let { it == a!! + b!! + c!! + d!! } } else { - mapN(a, b, c, d, { _, _, _, _ -> Unit }) == null + Nullable.mapN(a, b, c, d, { _, _, _, _ -> Unit }) == null } } } @@ -60,11 +60,11 @@ class NullableTest : StringSpec({ "map5 only performs action when all arguments are not null" { forAll(combGen(1, null, 5)) { (a: Int?, b: Int?, c: Int?, d: Int?, e: Int?) -> if (listOf(a, b, c, d, e).all { it != null }) { - mapN(a, b, c, d, e, { a, b, c, d, e -> a + b + c + d + e }).let { + Nullable.mapN(a, b, c, d, e, { a, b, c, d, e -> a + b + c + d + e }).let { it == a!! + b!! + c!! + d!! + e!! } } else { - mapN(a, b, c, d, e, { _, _, _, _, _ -> Unit }) == null + Nullable.mapN(a, b, c, d, e, { _, _, _, _, _ -> Unit }) == null } } } @@ -72,11 +72,11 @@ class NullableTest : StringSpec({ "map6 only performs action when all arguments are not null" { forAll(combGen(1, null, 6)) { (a: Int?, b: Int?, c: Int?, d: Int?, e: Int?, f: Int?) -> if (listOf(a, b, c, d, e, f).all { it != null }) { - mapN(a, b, c, d, e, f, { a, b, c, d, e, f -> a + b + c + d + e + f }).let { + Nullable.mapN(a, b, c, d, e, f, { a, b, c, d, e, f -> a + b + c + d + e + f }).let { it == a!! + b!! + c!! + d!! + e!! + f!! } } else { - mapN(a, b, c, d, e, f, { _, _, _, _, _, _ -> Unit }) == null + Nullable.mapN(a, b, c, d, e, f, { _, _, _, _, _, _ -> Unit }) == null } } } @@ -84,11 +84,11 @@ class NullableTest : StringSpec({ "map7 only performs action when all arguments are not null" { forAll(combGen(1, null, 7)) { (a: Int?, b: Int?, c: Int?, d: Int?, e: Int?, f: Int?, g: Int?) -> if (listOf(a, b, c, d, e, f, g).all { it != null }) { - mapN(a, b, c, d, e, f, g, { a, b, c, d, e, f, g -> a + b + c + d + e + f + g }).let { + Nullable.mapN(a, b, c, d, e, f, g, { a, b, c, d, e, f, g -> a + b + c + d + e + f + g }).let { it == a!! + b!! + c!! + d!! + e!! + f!! + g!! } } else { - mapN(a, b, c, d, e, f, g, { _, _, _, _, _, _, _ -> Unit }) == null + Nullable.mapN(a, b, c, d, e, f, g, { _, _, _, _, _, _, _ -> Unit }) == null } } } @@ -96,11 +96,11 @@ class NullableTest : StringSpec({ "map8 only performs action when all arguments are not null" { forAll(combGen(1, null, 8)) { (a: Int?, b: Int?, c: Int?, d: Int?, e: Int?, f: Int?, g: Int?, h: Int?) -> if (listOf(a, b, c, d, e, f, g, h).all { it != null }) { - mapN(a, b, c, d, e, f, g, h, { a, b, c, d, e, f, g, h -> a + b + c + d + e + f + g + h }).let { + Nullable.mapN(a, b, c, d, e, f, g, h, { a, b, c, d, e, f, g, h -> a + b + c + d + e + f + g + h }).let { it == a!! + b!! + c!! + d!! + e!! + f!! + g!! + h!! } } else { - mapN(a, b, c, d, e, f, g, h, { _, _, _, _, _, _, _, _ -> Unit }) == null + Nullable.mapN(a, b, c, d, e, f, g, h, { _, _, _, _, _, _, _, _ -> Unit }) == null } } } @@ -108,11 +108,11 @@ class NullableTest : StringSpec({ "map9 only performs action when all arguments are not null" { forAll(combGen(1, null, 9)) { (a: Int?, b: Int?, c: Int?, d: Int?, e: Int?, f: Int?, g: Int?, h: Int?, i: Int?) -> if (listOf(a, b, c, d, e, f, g, h, i).all { it != null }) { - mapN(a, b, c, d, e, f, g, h, i, { a, b, c, d, e, f, g, h, i -> a + b + c + d + e + f + g + h + i }).let { + Nullable.mapN(a, b, c, d, e, f, g, h, i, { a, b, c, d, e, f, g, h, i -> a + b + c + d + e + f + g + h + i }).let { it == a!! + b!! + c!! + d!! + e!! + f!! + g!! + h!! + i!! } } else { - mapN(a, b, c, d, e, f, g, h, i, { _, _, _, _, _, _, _, _, _ -> Unit }) == null + Nullable.mapN(a, b, c, d, e, f, g, h, i, { _, _, _, _, _, _, _, _, _ -> Unit }) == null } } } From b3f7280779afbb49d3a26aaf607bf16d7faca7c9 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Thu, 4 Mar 2021 14:19:30 +0100 Subject: [PATCH 2/2] Remove creation of intermediate lists in mapN --- .../src/main/kotlin/arrow/core/List.kt | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/List.kt b/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/List.kt index 5680cea996f..877bfe370f8 100644 --- a/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/List.kt +++ b/arrow-libs/core/arrow-core-data/src/main/kotlin/arrow/core/List.kt @@ -100,18 +100,19 @@ inline fun mapN( j: Iterable, k: Iterable, map: (B, C, D, E, F, G, H, I, J, K) -> L -): List = - b.flatMap { bb -> - c.flatMap { cc -> - d.flatMap { dd -> - e.flatMap { ee -> - f.flatMap { ff -> - g.flatMap { gg -> - h.flatMap { hh -> - i.flatMap { ii -> - j.flatMap { jj -> - k.map { kk -> - map(bb, cc, dd, ee, ff, gg, hh, ii, jj, kk) +): List { + val buffer = ArrayList() + for (bb in b) { + for (cc in c) { + for (dd in d) { + for (ee in e) { + for (ff in f) { + for (gg in g) { + for (hh in h) { + for (ii in i) { + for (jj in j) { + for (kk in k) { + buffer.add(map(bb, cc, dd, ee, ff, gg, hh, ii, jj, kk)) } } } @@ -122,6 +123,8 @@ inline fun mapN( } } } + return buffer +} fun Semigroup.Companion.list(): Semigroup> = Monoid.list()