diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Sequence.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Sequence.kt index 8e00e19fc78..7f67780684d 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Sequence.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Sequence.kt @@ -593,11 +593,13 @@ public fun Sequence.salign( * @receiver Iterable of Validated * @return a tuple containing Sequence with [Either.Left] and another Sequence with its [Either.Right] values. */ -public fun Sequence>.separateEither(): Pair, Sequence> { - val asep = flatMap { gab -> gab.fold({ sequenceOf(it) }, { emptySequence() }) } - val bsep = flatMap { gab -> gab.fold({ emptySequence() }, { sequenceOf(it) }) } - return asep to bsep -} +public fun Sequence>.separateEither(): Pair, Sequence> = + fold(sequenceOf() to sequenceOf()) { (lefts, rights), either -> + when (either) { + is Left -> lefts + either.value to rights + is Right -> lefts to rights + either.value + } + } /** * Separate the inner [Validated] values into the [Validated.Invalid] and [Validated.Valid]. @@ -605,11 +607,13 @@ public fun Sequence>.separateEither(): Pair, Seq * @receiver Iterable of Validated * @return a tuple containing Sequence with [Validated.Invalid] and another Sequence with its [Validated.Valid] values. */ -public fun Sequence>.separateValidated(): Pair, Sequence> { - val asep = flatMap { gab -> gab.fold({ sequenceOf(it) }, { emptySequence() }) } - val bsep = flatMap { gab -> gab.fold({ emptySequence() }, { sequenceOf(it) }) } - return asep to bsep -} +public fun Sequence>.separateValidated(): Pair, Sequence> = + fold(sequenceOf() to sequenceOf()) { (invalids, valids), validated -> + when (validated) { + is Valid -> invalids to valids + validated.value + is Invalid -> invalids + validated.value to valids + } + } public fun Sequence>.sequence(): Either> = traverse(::identity) diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/SequenceKTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/SequenceKTest.kt index 1ad6bffe6f2..8e77cffad6f 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/SequenceKTest.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/SequenceKTest.kt @@ -307,5 +307,31 @@ class SequenceKTest : UnitSpec() { ints.asSequence().filterOption().toList() shouldBe ints.filterOption() } } + + "separateEither" { + checkAll(Arb.sequence(Arb.int())) { ints -> + val sequence = ints.map { + if (it % 2 == 0) it.left() + else it.right() + } + + val (lefts, rights) = sequence.separateEither() + + lefts.toList() to rights.toList() shouldBe ints.partition { it % 2 == 0 } + } + } + + "separateValidated" { + checkAll(Arb.sequence(Arb.int())) { ints -> + val sequence = ints.map { + if (it % 2 == 0) it.invalid() + else it.valid() + } + + val (invalids, valids) = sequence.separateValidated() + + invalids.toList() to valids.toList() shouldBe ints.partition { it % 2 == 0 } + } + } } }