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

change unalign signature #2972

Merged
merged 6 commits into from
Mar 24, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -793,11 +793,14 @@ public inline fun <A, B, C> Iterable<C>.unzip(fc: (C) -> Pair<A, B>): Pair<List<
* ```
* <!--- KNIT example-iterable-13.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("separateIor()", "arrow.core.separateIor")
)
public fun <A, B> Iterable<Ior<A, B>>.unalign(): Pair<List<A>, List<B>> = separateIor()
public fun <A, B> Iterable<Ior<A, B>>.unalign(): Pair<List<A?>, List<B?>> =
fold(emptyList<A>() to emptyList()) { (l, r), x ->
x.fold(
{ Pair(l + it, r + null) },
{ Pair(l + null, r + it) },
{ a, b -> Pair(l + a, r + b) }
)
}

/**
* after applying the given function, splits the resulting union shaped structure into its components parts
Expand All @@ -817,11 +820,7 @@ public fun <A, B> Iterable<Ior<A, B>>.unalign(): Pair<List<A>, List<B>> = separa
* ```
* <!--- 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>> =
public inline fun <A, B, C> Iterable<C>.unalign(fa: (C) -> Ior<A, B>): Pair<List<A?>, List<B?>> =
map(fa).unalign()

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package arrow.core

import arrow.core.test.either
import arrow.core.test.functionAToB
import arrow.core.test.ior
import arrow.core.test.functionAToB
import arrow.core.test.option
import arrow.typeclasses.Semigroup
import io.kotest.core.spec.style.StringSpec
Expand Down Expand Up @@ -325,15 +325,29 @@ class IterableTest : StringSpec({
}

"unalign is the inverse of align" {
fun <A, B> Pair<List<A?>, List<B?>>.fix(): Pair<List<A>, List<B>> =
first.mapNotNull { it } to second.mapNotNull { it }

checkAll(Arb.list(Arb.int()), Arb.list(Arb.string())) { a, b ->
a.align(b).unalign() shouldBe (a to b)
a.align(b).unalign().fix() shouldBe (a to b)
}
}

"align is the inverse of unalign" {
fun <A, B> Ior<A?, B?>.fix(): Ior<A, B> =
fold({ Ior.Left(it!!) }, { Ior.Right(it!!) }, { a, b ->
when {
a == null -> Ior.Right(b!!)
b == null -> Ior.Left(a)
else -> Ior.Both(a, b)
}
})

checkAll(Arb.list(Arb.ior(Arb.int(), Arb.string()))) { xs ->
val (a, b) = xs.unalign()
a.align(b) shouldBe xs
a.align(b) {
it.fix()
} shouldBe xs
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,12 @@ fun <A, B> Arb.Companion.ior(arbA: Arb<A>, arbB: Arb<B>): Arb<Ior<A, B>> =
arbA.alignWith(arbB) { it }

private fun <A, B, R> Arb<A>.alignWith(arbB: Arb<B>, transform: (Ior<A, B>) -> R): Arb<R> =
Arb.bind(this, arbB) { a, b -> transform(Ior.Both(a, b)) }
Arb.choice(
this.map { Ior.Left(it) },
Arb.bind(this, arbB) { a, b -> Ior.Both(a, b) },
arbB.map { Ior.Right(it) }
).map(transform)


fun Arb.Companion.suspendFunThatReturnsEitherAnyOrAnyOrThrows(): Arb<suspend () -> Either<Any, Any>> =
choice(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package arrow.core.test

import io.kotest.assertions.assertSoftly
import io.kotest.core.spec.style.StringSpec
import io.kotest.inspectors.forAtLeastOne
import io.kotest.matchers.booleans.shouldBeTrue
import io.kotest.property.Arb
import io.kotest.property.arbitrary.int
import io.kotest.property.arbitrary.list
import io.kotest.property.arbitrary.next
import io.kotest.property.arbitrary.string

class GeneratorsTest : StringSpec({
"Arb.ior should generate Left, Right & Both" {
assertSoftly(Arb.list(Arb.ior(Arb.string(), Arb.int()), range = 20 .. 100).next()) {
forAtLeastOne {
it.isRight().shouldBeTrue()
}
forAtLeastOne {
it.isBoth().shouldBeTrue()
}
forAtLeastOne {
it.isLeft().shouldBeTrue()
}
}
}
})