From a1fffdb709c7cb622f8259b569a005056ddce2d0 Mon Sep 17 00:00:00 2001 From: Alphonse Bendt <370821+abendt@users.noreply.github.com> Date: Thu, 9 Mar 2023 09:20:39 +0100 Subject: [PATCH] Iterable test (#2960) Co-authored-by: Simon Vergauwen --- arrow-libs/core/arrow-core/api/arrow-core.api | 1 + .../commonMain/kotlin/arrow/core/Iterable.kt | 32 ++++++-- .../kotlin/arrow/core/IterableTest.kt | 77 +++++++++++++++++++ 3 files changed, 102 insertions(+), 8 deletions(-) diff --git a/arrow-libs/core/arrow-core/api/arrow-core.api b/arrow-libs/core/arrow-core/api/arrow-core.api index 838a55a597a..b5314b63caa 100644 --- a/arrow-libs/core/arrow-core/api/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/arrow-core.api @@ -650,6 +650,7 @@ public final class arrow/core/IterableKt { public static final fun rightPadZip (Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)Ljava/util/List; public static final fun salign (Ljava/lang/Iterable;Larrow/typeclasses/Semigroup;Ljava/lang/Iterable;)Ljava/lang/Iterable; public static final fun separateEither (Ljava/lang/Iterable;)Lkotlin/Pair; + public static final fun separateIor (Ljava/lang/Iterable;)Lkotlin/Pair; public static final fun separateValidated (Ljava/lang/Iterable;)Lkotlin/Pair; public static final fun sequence (Ljava/lang/Iterable;)Larrow/core/Either; public static final fun sequence (Ljava/lang/Iterable;)Larrow/core/Option; diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Iterable.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Iterable.kt index e44b03055c5..7d053beaeec 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Iterable.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Iterable.kt @@ -867,14 +867,11 @@ public inline fun Iterable.unzip(fc: (C) -> Pair): Pair */ -public fun Iterable>.unalign(): Pair, List> = - fold(emptyList() to emptyList()) { (l, r), x -> - x.fold( - { l + it to r }, - { l to r + it }, - { a, b -> l + a to r + b } - ) - } +@Deprecated( + "The current unalign function is renamed to separateIor, and a new unalign function is going to be added to Arrow 2.0.0.", + ReplaceWith("separateIor()", "arrow.core.separateIor") +) +public fun Iterable>.unalign(): Pair, List> = separateIor() /** * after applying the given function, splits the resulting union shaped structure into its components parts @@ -894,9 +891,28 @@ public fun Iterable>.unalign(): Pair, List> = * ``` * */ +@Deprecated( + "The current unalign function is renamed to separateIor, and a new unalign function is going to be added to Arrow 2.0.0.", + ReplaceWith("map(fa).separateIor()", "arrow.core.separateIor") +) public inline fun Iterable.unalign(fa: (C) -> Ior): Pair, List> = map(fa).unalign() +/** + * Separate the inner [Ior] values into a pair of Lists. + * + * @receiver Iterable of Ior + * @return a tuple containing a List with the left side value from the[Ior.Left] and [Ior.Both] values and another List with the right side value from the [Ior.Right] and [Ior.Both] values. + */ +public fun Iterable>.separateIor(): Pair, List> = + fold(emptyList() to emptyList()) { (l, r), x -> + x.fold( + { l + it to r }, + { l to r + it }, + { a, b -> l + a to r + b } + ) + } + @Deprecated("use fold instead", ReplaceWith("fold(MA)", "arrow.core.fold")) public fun Iterable.combineAll(MA: Monoid): A = fold(MA) diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/IterableTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/IterableTest.kt index c8f085283c7..ce052f3513a 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/IterableTest.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/IterableTest.kt @@ -2,6 +2,7 @@ package arrow.core import arrow.core.test.either import arrow.core.test.functionAToB +import arrow.core.test.ior import arrow.core.test.option import arrow.typeclasses.Semigroup import io.kotest.core.spec.style.StringSpec @@ -14,6 +15,7 @@ import io.kotest.property.arbitrary.boolean import io.kotest.property.arbitrary.int 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.checkAll import kotlin.math.max @@ -551,4 +553,79 @@ class IterableTest : StringSpec({ } } + "unzip is the inverse of zip" { + checkAll(Arb.list(Arb.int())) { xs -> + + val zipped = xs.zip(xs) + val ls = zipped.unzip() + val rs = xs to xs + + ls shouldBe rs + } + } + + "unzip(fn)" { + checkAll(Arb.list(Arb.pair(Arb.int(), Arb.string()))) { xs -> + xs.unzip { it } shouldBe xs.unzip() + } + } + + "unalign is the inverse of align" { + checkAll(Arb.list(Arb.int()), Arb.list(Arb.string())) { a, b -> + a.align(b).unalign() shouldBe (a to b) + } + } + + "align is the inverse of unalign" { + checkAll(Arb.list(Arb.ior(Arb.int(), Arb.string()))) { xs -> + val (a, b) = xs.unalign() + a.align(b) shouldBe xs + } + } + + "unalign(fn)" { + checkAll(Arb.list(Arb.ior(Arb.int(), Arb.string()))) { xs -> + xs.unalign { it } shouldBe xs.unalign() + } + } + + "salign" { + checkAll(Arb.list(Arb.int())) { xs -> + xs.salign(Semigroup.int(), xs) shouldBe xs.map { it + it } + } + } + + "reduceOrNull is compatible with reduce from stdlib" { + checkAll(Arb.list(Arb.string())) { xs -> + + val rs = xs.reduceOrNull({ it }) { a, b -> + a + b + } + + if (xs.isEmpty()) { + rs.shouldBeNull() + } else { + rs shouldBe xs.reduce { + a,b -> a +b + } + } + } + } + + "reduceRightNull is compatible with reduce from stdlib" { + checkAll(Arb.list(Arb.string())) { xs -> + + val rs = xs.reduceRightNull({ it }) { a, b -> + a + b + } + + if (xs.isEmpty()) { + rs.shouldBeNull() + } else { + rs shouldBe xs.reduceRight { + a,b -> a +b + } + } + } + } })