Skip to content

Commit

Permalink
change unalign signature
Browse files Browse the repository at this point in the history
  • Loading branch information
abendt committed Mar 9, 2023
1 parent 3761000 commit ea08474
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -683,11 +683,11 @@ public inline fun <A, B, C> Iterable<C>.unzip(fc: (C) -> Pair<A, B>): Pair<List<
* ```
* <!--- KNIT example-iterable-11.kt -->
*/
public fun <A, B> Iterable<Ior<A, B>>.unalign(): Pair<List<A>, List<B>> =
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 },
{ l + it to r + null},
{ l + null to r + it },
{ a, b -> l + a to r + b }
)
}
Expand All @@ -710,7 +710,7 @@ public fun <A, B> Iterable<Ior<A, B>>.unalign(): Pair<List<A>, List<B>> =
* ```
* <!--- KNIT example-iterable-12.kt -->
*/
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()

@Deprecated("use fold instead", ReplaceWith("fold(MA)", "arrow.core.fold"))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package arrow.core

import arrow.core.test.either
import arrow.core.test.ior
import arrow.core.test.option
import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.nulls.shouldNotBeNull
Expand Down Expand Up @@ -301,4 +302,34 @@ 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().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) {
it.fix()
} shouldBe xs
}
}

"unalign(fn)" {
checkAll(Arb.list(Arb.ior(Arb.int(), Arb.string()))) { xs ->
xs.unalign { it } shouldBe xs.unalign()
}
}
})
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())).next()) {
forAtLeastOne {
it.isRight.shouldBeTrue()
}
forAtLeastOne {
it.isBoth.shouldBeTrue()
}
forAtLeastOne {
it.isLeft.shouldBeTrue()
}
}
}
})

0 comments on commit ea08474

Please sign in to comment.