Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iterable test #2960

Merged
merged 11 commits into from
Mar 9, 2023
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions arrow-libs/core/arrow-core/api/arrow-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,7 @@ public inline fun <A, B, C> Iterable<A>.align(b: Iterable<B>, fa: (Ior<A, B>) ->
first.hasNext() && second.hasNext() -> Ior.Both(first.next(), second.next())
first.hasNext() -> first.next().leftIor()
second.hasNext() -> second.next().rightIor()
else -> throw IllegalStateException("this should never happen")
else -> throw AssertionError("this should never happen")
nomisRev marked this conversation as resolved.
Show resolved Hide resolved
}
add(fa(element))
}
Expand Down Expand Up @@ -877,14 +877,11 @@ public inline fun <A, B, C> Iterable<C>.unzip(fc: (C) -> Pair<A, B>): Pair<List<
* ```
* <!--- KNIT example-iterable-13.kt -->
*/
public fun <A, B> Iterable<Ior<A, B>>.unalign(): Pair<List<A>, List<B>> =
fold(emptyList<A>() 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 <A, B> Iterable<Ior<A, B>>.unalign(): Pair<List<A>, List<B>> = separateIor()

/**
* after applying the given function, splits the resulting union shaped structure into its components parts
Expand All @@ -904,9 +901,28 @@ public fun <A, B> Iterable<Ior<A, B>>.unalign(): Pair<List<A>, List<B>> =
* ```
* <!--- KNIT example-iterable-14.kt -->
*/
@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 <A, B, C> Iterable<C>.unalign(fa: (C) -> Ior<A, B>): Pair<List<A>, List<B>> =
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 <A, B> Iterable<Ior<A, B>>.separateIor(): Pair<List<A>, List<B>> =
fold(emptyList<A>() 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 <A> Iterable<A>.combineAll(MA: Monoid<A>): A =
fold(MA)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -551,4 +553,87 @@ 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()
}
}

"zip is the inverse of unzip" {
checkAll(Arb.list(Arb.pair(Arb.int(), Arb.string()))) { xs ->
val (l, r) = xs.unzip()

l.zip(r) shouldBe xs
}
}
nomisRev marked this conversation as resolved.
Show resolved Hide resolved

"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
}
}
}
}
})