Skip to content

Commit

Permalink
add Iterable.crosswalk tests (#2894)
Browse files Browse the repository at this point in the history
  • Loading branch information
jsoizo committed Apr 25, 2023
1 parent d3a72af commit af88e21
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1265,6 +1265,21 @@ public fun <A> Iterable<A>.fold(MA: Monoid<A>): A =
public fun <A, B> Iterable<A>.foldMap(MB: Monoid<B>, f: (A) -> B): B =
fold(MB.empty()) { acc, a -> MB.run { acc.combine(f(a)) } }

/**
* Applies function [f] to each element
* and returns a list for the applied result Iterable<B>.
*
* ```kotlin
* import arrow.core.crosswalk
* import io.kotest.matchers.shouldBe
*
* fun test() {
* val ints = listOf(1, 2)
* val res = ints.crosswalk { i -> listOf("a${i}", "b${i}", "c${i}") }
* res shouldBe listOf(listOf("a2", "a1"), listOf("b2", "b1"), listOf("c2", "c1"))
* }
* ```
*/
public fun <A, B> Iterable<A>.crosswalk(f: (A) -> Iterable<B>): List<List<B>> =
fold(emptyList()) { bs, a ->
f(a).align(bs) { ior ->
Expand All @@ -1276,6 +1291,21 @@ public fun <A, B> Iterable<A>.crosswalk(f: (A) -> Iterable<B>): List<List<B>> =
}
}

/**
* Applies function [f] to each element
* and returns the concatenated Map of the applied result Map<K, V>.
*
* ```kotlin
* import arrow.core.crosswalk
* import io.kotest.matchers.shouldBe
*
* fun test() {
* val ints = listOf(1, 2)
* val res = ints.crosswalkMap { i -> mapOf("a" to i, "b" to i, "c" to i) }
* res shouldBe listOf("a", "b", "c").map { a -> a to ints.reversed() }.toMap()
* }
* ```
*/
public fun <A, K, V> Iterable<A>.crosswalkMap(f: (A) -> Map<K, V>): Map<K, List<V>> =
fold(emptyMap()) { bs, a ->
f(a).align(bs) { (_, ior) ->
Expand All @@ -1287,6 +1317,21 @@ public fun <A, K, V> Iterable<A>.crosswalkMap(f: (A) -> Map<K, V>): Map<K, List<
}
}

/**
* Applies function [f] to each element
* and returns the result Iterable<B> without null.
*
* ```kotlin
* import arrow.core.crosswalk
* import io.kotest.matchers.shouldBe
*
* fun test() {
* val ints = listOf(1, 2)
* val res = ints.crosswalkNull { i -> if (i % 2 == 0) "x${i}" else null }
* res shouldBe listOf("x2")
* }
* ```
*/
public fun <A, B> Iterable<A>.crosswalkNull(f: (A) -> B?): List<B>? =
fold<A, List<B>?>(emptyList()) { bs, a ->
Ior.fromNullables(f(a), bs)?.fold(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import io.kotest.property.arbitrary.list
import io.kotest.property.arbitrary.orNull
import io.kotest.property.arbitrary.pair
import io.kotest.property.arbitrary.string
import io.kotest.property.arbitrary.char
import io.kotest.property.checkAll
import kotlin.math.max
import kotlin.math.min
Expand Down Expand Up @@ -663,4 +664,32 @@ class IterableTest : StringSpec({
listOf(1,2,3).compareTo(listOf(1,1,3)) shouldBe 1
}

"crosswalk" {
checkAll(Arb.pair(Arb.list(Arb.int()), Arb.list(Arb.char()))) { (ints, chars) ->
val res = ints.crosswalk { i -> chars.map { c -> "${c}${i}" } }
val expected =
if (ints.isNotEmpty()) chars.map { c -> ints.reversed().map { i -> "${c}${i}" } }
else emptyList()
res shouldBe expected
}
}

"crosswalkMap" {
checkAll(Arb.pair(Arb.list(Arb.int()), Arb.list(Arb.char()))) { (ints, chars) ->
val res = ints.crosswalkMap { i -> chars.map { c -> c to i }.toMap() }
val expected =
if (ints.isNotEmpty()) chars.map { c -> c to ints.reversed() }.toMap()
else emptyMap()
res shouldBe expected
}
}

"crosswalkNull" {
checkAll(Arb.list(Arb.int())) { ints ->
val res = ints.crosswalkNull { i -> if (i % 2 == 0) "x${i}" else null }
val expected = ints.mapNotNull { i -> if (i % 2 == 0 ) "x${i}" else null }.reversed()
res shouldBe expected
}
}

})

0 comments on commit af88e21

Please sign in to comment.