From e94dc2ec844ae14e17b9bbaa0a7d78595d02542a Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Wed, 8 Mar 2023 08:38:14 +0100 Subject: [PATCH] Update Raise.xOrAccumulate (#2958) --- arrow-libs/core/arrow-core/api/arrow-core.api | 35 +- .../commonMain/kotlin/arrow/core/Iterable.kt | 22 +- .../arrow/core/raise/RaiseAccumulate.kt | 725 ++++++++---------- 3 files changed, 337 insertions(+), 445 deletions(-) diff --git a/arrow-libs/core/arrow-core/api/arrow-core.api b/arrow-libs/core/arrow-core/api/arrow-core.api index 9ece638d6dd..838a55a597a 100644 --- a/arrow-libs/core/arrow-core/api/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/arrow-core.api @@ -3456,9 +3456,8 @@ public final class arrow/core/raise/RaiseKt { public static final fun getOrNull (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun getOrNull (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun ior (Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;)Larrow/core/Ior; - public static final fun mapErrorNel (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun mapOrAccumulate (Larrow/core/raise/Raise;Larrow/typeclasses/Semigroup;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)Ljava/util/List; public static final fun mapOrAccumulate (Larrow/core/raise/Raise;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)Ljava/util/List; + public static final fun mapOrAccumulate (Larrow/core/raise/Raise;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Ljava/util/List; public static final fun merge (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun merge (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun nullable (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; @@ -3483,22 +3482,22 @@ public final class arrow/core/raise/RaiseKt { public static final fun toResult (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun toValidated (Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; public static final fun toValidated (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function10;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function9;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function8;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function7;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function6;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function5;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function4;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function10;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function9;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function8;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function7;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function6;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function5;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function4;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function9;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function8;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function7;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function6;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function5;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function4;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function9;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function8;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function7;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function6;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function5;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function4;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; } public final class arrow/core/raise/ResultRaise : arrow/core/raise/Raise { 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 c62347e4af2..e44b03055c5 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 @@ -9,7 +9,9 @@ import arrow.core.Either.Left import arrow.core.Either.Right import arrow.core.raise.Raise import arrow.core.raise.RaiseAccumulate +import arrow.core.raise.either import arrow.core.raise.fold +import arrow.core.raise.mapOrAccumulate import arrow.typeclasses.Monoid import arrow.typeclasses.Semigroup import kotlin.Result.Companion.success @@ -481,16 +483,8 @@ public fun Iterable.sequenceNullable(): List? = public inline fun Iterable.mapOrAccumulate( combine: (Error, Error) -> Error, @BuilderInference transform: RaiseAccumulate.(A) -> B, -): Either> { - var left: Any? = EmptyValue - val right = ArrayList(collectionSizeOrDefault(10)) - for (item in this) - fold( - { transform(RaiseAccumulate(this), item) }, - { errors -> left = EmptyValue.combine(left, errors.reduce(combine), combine) }, - { b -> right.add(b) } - ) - return if (left !== EmptyValue) EmptyValue.unbox(left).left() else right.right() +): Either> = either { + mapOrAccumulate(this@mapOrAccumulate, combine, transform) } /** @@ -523,12 +517,8 @@ public inline fun Iterable.mapOrAccumulate( @OptIn(ExperimentalTypeInference::class) public inline fun Iterable.mapOrAccumulate( @BuilderInference transform: RaiseAccumulate.(A) -> B, -): Either, List> { - val left = mutableListOf() - val right = ArrayList(collectionSizeOrDefault(10)) - for (item in this) - fold({ transform(RaiseAccumulate(this), item) }, { error -> left.addAll(error) }, { b -> right.add(b) }) - return left.toNonEmptyListOrNull()?.left() ?: right.right() +): Either, List> = either { + mapOrAccumulate(this@mapOrAccumulate, transform) } /** diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/RaiseAccumulate.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/RaiseAccumulate.kt index f62f0700531..af77863614b 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/RaiseAccumulate.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/RaiseAccumulate.kt @@ -7,280 +7,234 @@ import arrow.core.mapOrAccumulate import arrow.core.Either import arrow.core.EitherNel import arrow.core.EmptyValue +import arrow.core.EmptyValue.combine +import arrow.core.EmptyValue.unbox import arrow.core.NonEmptyList -import arrow.core.Tuple4 -import arrow.core.Tuple5 -import arrow.core.Tuple6 -import arrow.core.Tuple7 -import arrow.core.Tuple8 import arrow.core.Validated +import arrow.core.collectionSizeOrDefault import arrow.core.ValidatedNel -import arrow.core.emptyCombine -import arrow.core.identity -import arrow.core.nel import arrow.core.nonEmptyListOf -import arrow.typeclasses.Semigroup +import arrow.core.toNonEmptyListOrNull import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.InvocationKind +import kotlin.contracts.InvocationKind.AT_MOST_ONCE import kotlin.contracts.contract import kotlin.experimental.ExperimentalTypeInference -import kotlin.js.JsName import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName /** - * Accumulate the errors from running both [action1] and [action2] - * using the given [semigroup]. + * Accumulate the errors from running both [action1] and [action2] using the given [combine] function. */ @RaiseDSL public inline fun Raise.zipOrAccumulate( - semigroup: Semigroup<@UnsafeVariance R>, - @BuilderInference action1: Raise.() -> A, - @BuilderInference action2: Raise.() -> B, - @BuilderInference block: Raise.(A, B) -> C + combine: (R, R) -> R, + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + block: (A, B) -> C ): C { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - } - val result1 = either(action1) - val result2 = either(action2) - return when (result1) { - is Either.Right -> - when (result2) { - is Either.Right -> block(result1.value, result2.value) - is Either.Left -> raise(result2.value) - } - is Either.Left -> - when (result2) { - is Either.Right -> raise(result1.value) - is Either.Left -> raise(semigroup.run { result1.value + result2.value }) - } + contract { callsInPlace(block, AT_MOST_ONCE) } + return zipOrAccumulate( + combine, + action1, + action2, + { }) { a, b, _ -> + block(a, b) } } /** - * Accumulate the errors from running [action1], [action2], and [action3] - * using the given [semigroup]. + * Accumulate the errors from running [action1], [action2], and [action3] using the given [combine]. */ @RaiseDSL public inline fun Raise.zipOrAccumulate( - semigroup: Semigroup<@UnsafeVariance R>, - @BuilderInference action1: Raise.() -> A, - @BuilderInference action2: Raise.() -> B, - @BuilderInference action3: Raise.() -> C, - @BuilderInference block: Raise.(A, B, C) -> D + combine: (R, R) -> R, + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + block: (A, B, C) -> D ): D { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - semigroup, - { zipOrAccumulate(semigroup, action1, action2) { x, y -> x to y } }, - action3 - ) { xy, z -> block(xy.first, xy.second, z) } + combine, + action1, + action2, + action3, + { }) { a, b, c, _ -> + block(a, b, c) + } } /** - * Accumulate the errors from running [action1], [action2], [action3], and [action4] - * using the given [semigroup]. + * Accumulate the errors from running [action1], [action2], [action3], and [action4] using the given [combine]. */ @RaiseDSL public inline fun Raise.zipOrAccumulate( - semigroup: Semigroup<@UnsafeVariance R>, - @BuilderInference action1: Raise.() -> A, - @BuilderInference action2: Raise.() -> B, - @BuilderInference action3: Raise.() -> C, - @BuilderInference action4: Raise.() -> D, - @BuilderInference block: Raise.(A, B, C, D) -> E + combine: (R, R) -> R, + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + block: (A, B, C, D) -> E ): E { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - semigroup, - { zipOrAccumulate(semigroup, action1, action2, action3) { x, y, z -> Triple(x, y, z) } }, - action4 - ) { xyz, z -> block(xyz.first, xyz.second, xyz.third, z) } + combine, + action1, + action2, + action3, + action4, + { }) { a, b, c, d, _ -> + block(a, b, c, d) + } } /** - * Accumulate the errors from running [action1], [action2], [action3], [action4], and [action5] - * using the given [semigroup]. + * Accumulate the errors from running [action1], [action2], [action3], [action4], and [action5] using the given [combine]. */ @RaiseDSL public inline fun Raise.zipOrAccumulate( - semigroup: Semigroup<@UnsafeVariance R>, - @BuilderInference action1: Raise.() -> A, - @BuilderInference action2: Raise.() -> B, - @BuilderInference action3: Raise.() -> C, - @BuilderInference action4: Raise.() -> D, - @BuilderInference action5: Raise.() -> E, - @BuilderInference block: Raise.(A, B, C, D, E) -> F + combine: (R, R) -> R, + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + @BuilderInference action5: RaiseAccumulate.() -> E, + block: (A, B, C, D, E) -> F ): F { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - callsInPlace(action5, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - semigroup, - { zipOrAccumulate(semigroup, action1, action2, action3, action4) { x, y, z, u -> Tuple4(x, y, z, u) } }, - action5 - ) { xyzu, v -> block(xyzu.first, xyzu.second, xyzu.third, xyzu.fourth, v) } + combine, + action1, + action2, + action3, + action4, + action5, + { }) { a, b, c, d, e, _ -> + block(a, b, c, d, e) + } } /** - * Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], and [action6] - * using the given [semigroup]. + * Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], and [action6] using the given [combine]. */ @RaiseDSL public inline fun Raise.zipOrAccumulate( - semigroup: Semigroup<@UnsafeVariance R>, - @BuilderInference action1: Raise.() -> A, - @BuilderInference action2: Raise.() -> B, - @BuilderInference action3: Raise.() -> C, - @BuilderInference action4: Raise.() -> D, - @BuilderInference action5: Raise.() -> E, - @BuilderInference action6: Raise.() -> F, - @BuilderInference block: Raise.(A, B, C, D, E, F) -> G + combine: (R, R) -> R, + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + @BuilderInference action5: RaiseAccumulate.() -> E, + @BuilderInference action6: RaiseAccumulate.() -> F, + block: (A, B, C, D, E, F) -> G ): G { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - callsInPlace(action5, InvocationKind.EXACTLY_ONCE) - callsInPlace(action6, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - semigroup, - { zipOrAccumulate(semigroup, action1, action2, action3, action4, action5) { x, y, z, u, v -> Tuple5(x, y, z, u, v) } }, - action6 - ) { xyzuv, w -> block(xyzuv.first, xyzuv.second, xyzuv.third, xyzuv.fourth, xyzuv.fifth, w) } + combine, + action1, + action2, + action3, + action4, + action5, + action6, + { }) { a, b, c, d, e, f, _ -> + block(a, b, c, d, e, f) + } } /** - * Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], [action6], and [action7] - * using the given [semigroup]. + * Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], [action6], and [action7] using the given [combine]. */ @RaiseDSL public inline fun Raise.zipOrAccumulate( - semigroup: Semigroup<@UnsafeVariance R>, - @BuilderInference action1: Raise.() -> A, - @BuilderInference action2: Raise.() -> B, - @BuilderInference action3: Raise.() -> C, - @BuilderInference action4: Raise.() -> D, - @BuilderInference action5: Raise.() -> E, - @BuilderInference action6: Raise.() -> F, - @BuilderInference action7: Raise.() -> G, - @BuilderInference block: Raise.(A, B, C, D, E, F, G) -> H + combine: (R, R) -> R, + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + @BuilderInference action5: RaiseAccumulate.() -> E, + @BuilderInference action6: RaiseAccumulate.() -> F, + @BuilderInference action7: RaiseAccumulate.() -> G, + block: (A, B, C, D, E, F, G) -> H ): H { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - callsInPlace(action5, InvocationKind.EXACTLY_ONCE) - callsInPlace(action6, InvocationKind.EXACTLY_ONCE) - callsInPlace(action7, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - semigroup, - { zipOrAccumulate(semigroup, action1, action2, action3, action4, action5, action6) { x, y, z, u, v, w -> Tuple6(x, y, z, u, v, w) } }, - action7 - ) { xyzuvw, a -> block(xyzuvw.first, xyzuvw.second, xyzuvw.third, xyzuvw.fourth, xyzuvw.fifth, xyzuvw.sixth, a) } + combine, + action1, + action2, + action3, + action4, + action5, + action6, + action7, + { }) { a, b, c, d, e, f, g, _ -> + block(a, b, c, d, e, f, g) + } } /** - * Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], [action6], [action7], and [action8] - * using the given [semigroup]. + * Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], [action6], [action7], and [action8] using the given [combine]. */ @RaiseDSL public inline fun Raise.zipOrAccumulate( - semigroup: Semigroup<@UnsafeVariance R>, - @BuilderInference action1: Raise.() -> A, - @BuilderInference action2: Raise.() -> B, - @BuilderInference action3: Raise.() -> C, - @BuilderInference action4: Raise.() -> D, - @BuilderInference action5: Raise.() -> E, - @BuilderInference action6: Raise.() -> F, - @BuilderInference action7: Raise.() -> G, - @BuilderInference action8: Raise.() -> H, - @BuilderInference block: Raise.(A, B, C, D, E, F, G, H) -> I + combine: (R, R) -> R, + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + @BuilderInference action5: RaiseAccumulate.() -> E, + @BuilderInference action6: RaiseAccumulate.() -> F, + @BuilderInference action7: RaiseAccumulate.() -> G, + @BuilderInference action8: RaiseAccumulate.() -> H, + block: (A, B, C, D, E, F, G, H) -> I ): I { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - callsInPlace(action5, InvocationKind.EXACTLY_ONCE) - callsInPlace(action6, InvocationKind.EXACTLY_ONCE) - callsInPlace(action7, InvocationKind.EXACTLY_ONCE) - callsInPlace(action8, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - semigroup, - { zipOrAccumulate(semigroup, action1, action2, action3, action4, action5, action6, action7) { x, y, z, u, v, w, a -> Tuple7(x, y, z, u, v, w, a) } }, - action8 - ) { xyzuvwa, b -> block(xyzuvwa.first, xyzuvwa.second, xyzuvwa.third, xyzuvwa.fourth, xyzuvwa.fifth, xyzuvwa.sixth, xyzuvwa.seventh, b) } + combine, + action1, + action2, + action3, + action4, + action5, + action6, + action7, + action8, + { }) { a, b, c, d, e, f, g, h, _ -> + block(a, b, c, d, e, f, g, h) + } } /** - * Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], [action6], [action7], [action8], and [action9] - * using the given [semigroup]. + * Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], [action6], [action7], [action8], and [action9] using the given [combine]. */ @RaiseDSL public inline fun Raise.zipOrAccumulate( - semigroup: Semigroup<@UnsafeVariance R>, - @BuilderInference action1: Raise.() -> A, - @BuilderInference action2: Raise.() -> B, - @BuilderInference action3: Raise.() -> C, - @BuilderInference action4: Raise.() -> D, - @BuilderInference action5: Raise.() -> E, - @BuilderInference action6: Raise.() -> F, - @BuilderInference action7: Raise.() -> G, - @BuilderInference action8: Raise.() -> H, - @BuilderInference action9: Raise.() -> I, - @BuilderInference block: Raise.(A, B, C, D, E, F, G, H, I) -> J + combine: (R, R) -> R, + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + @BuilderInference action5: RaiseAccumulate.() -> E, + @BuilderInference action6: RaiseAccumulate.() -> F, + @BuilderInference action7: RaiseAccumulate.() -> G, + @BuilderInference action8: RaiseAccumulate.() -> H, + @BuilderInference action9: RaiseAccumulate.() -> I, + block: (A, B, C, D, E, F, G, H, I) -> J ): J { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - callsInPlace(action5, InvocationKind.EXACTLY_ONCE) - callsInPlace(action6, InvocationKind.EXACTLY_ONCE) - callsInPlace(action7, InvocationKind.EXACTLY_ONCE) - callsInPlace(action8, InvocationKind.EXACTLY_ONCE) - callsInPlace(action9, InvocationKind.EXACTLY_ONCE) - } - return zipOrAccumulate( - semigroup, - { zipOrAccumulate(semigroup, action1, action2, action3, action4, action5, action6, action7, action8) { x, y, z, u, v, w, a, b -> Tuple8(x, y, z, u, v, w, a, b) } }, - action9 - ) { xyzuvwab, c -> block(xyzuvwab.first, xyzuvwab.second, xyzuvwab.third, xyzuvwab.fourth, xyzuvwab.fifth, xyzuvwab.sixth, xyzuvwab.seventh, xyzuvwab.eighth, c) } -} - -/** - * Re-raise any errors in [block] in a [NonEmptyList]. - */ -@RaiseDSL -public inline fun Raise>.mapErrorNel( - crossinline block: Raise.() -> A -): A { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - } - return recover(block) { raise(it.nel()) } + contract { callsInPlace(block, AT_MOST_ONCE) } + var error: Any? = EmptyValue + val a = recover({ action1(RaiseAccumulate(this)) }) { error = combine(error, it.reduce(combine), combine); EmptyValue } + val b = recover({ action2(RaiseAccumulate(this)) }) { error = combine(error, it.reduce(combine), combine); EmptyValue } + val c = recover({ action3(RaiseAccumulate(this)) }) { error = combine(error, it.reduce(combine), combine); EmptyValue } + val d = recover({ action4(RaiseAccumulate(this)) }) { error = combine(error, it.reduce(combine), combine); EmptyValue } + val e = recover({ action5(RaiseAccumulate(this)) }) { error = combine(error, it.reduce(combine), combine); EmptyValue } + val f = recover({ action6(RaiseAccumulate(this)) }) { error = combine(error, it.reduce(combine), combine); EmptyValue } + val g = recover({ action7(RaiseAccumulate(this)) }) { error = combine(error, it.reduce(combine), combine); EmptyValue } + val h = recover({ action8(RaiseAccumulate(this)) }) { error = combine(error, it.reduce(combine), combine); EmptyValue } + val i = recover({ action9(RaiseAccumulate(this)) }) { error = combine(error, it.reduce(combine), combine); EmptyValue } + return if (error !== EmptyValue) raise(unbox(error)) + else block(unbox(a), unbox(b), unbox(c), unbox(d), unbox(e), unbox(f), unbox(g), unbox(h), unbox(i)) } /** @@ -288,20 +242,17 @@ public inline fun Raise>.mapErrorNel( */ @RaiseDSL public inline fun Raise>.zipOrAccumulate( - @BuilderInference crossinline action1: Raise.() -> A, - @BuilderInference crossinline action2: Raise.() -> B, - @BuilderInference crossinline block: Raise.(A, B) -> C + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + block: (A, B) -> C ): C { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - Semigroup.nonEmptyList(), - { mapErrorNel(action1) }, - { mapErrorNel(action2) }, - { x, y -> mapErrorNel { block(x, y) } } - ) + action1, + action2, + {}) { a, b, _ -> + block(a, b) + } } /** @@ -309,23 +260,19 @@ public inline fun Raise>.zipOrAccumulate( */ @RaiseDSL public inline fun Raise>.zipOrAccumulate( - @BuilderInference crossinline action1: Raise.() -> A, - @BuilderInference crossinline action2: Raise.() -> B, - @BuilderInference crossinline action3: Raise.() -> C, - @BuilderInference crossinline block: Raise.(A, B, C) -> D + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + block: (A, B, C) -> D ): D { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - Semigroup.nonEmptyList(), - { mapErrorNel(action1) }, - { mapErrorNel(action2) }, - { mapErrorNel(action3) }, - { x, y, z -> mapErrorNel { block(x, y, z) } } - ) + action1, + action2, + action3, + {}) { a, b, c, _ -> + block(a, b, c) + } } /** @@ -333,26 +280,21 @@ public inline fun Raise>.zipOrAccumulate( */ @RaiseDSL public inline fun Raise>.zipOrAccumulate( - @BuilderInference crossinline action1: Raise.() -> A, - @BuilderInference crossinline action2: Raise.() -> B, - @BuilderInference crossinline action3: Raise.() -> C, - @BuilderInference crossinline action4: Raise.() -> D, - @BuilderInference crossinline block: Raise.(A, B, C, D) -> E + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + block: (A, B, C, D) -> E ): E { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - Semigroup.nonEmptyList(), - { mapErrorNel(action1) }, - { mapErrorNel(action2) }, - { mapErrorNel(action3) }, - { mapErrorNel(action4) }, - { x, y, z, u -> mapErrorNel { block(x, y, z, u) } } - ) + action1, + action2, + action3, + action4, + {}) { a, b, c, d, _ -> + block(a, b, c, d) + } } /** @@ -360,29 +302,23 @@ public inline fun Raise>.zipOrAccumulate( */ @RaiseDSL public inline fun Raise>.zipOrAccumulate( - @BuilderInference crossinline action1: Raise.() -> A, - @BuilderInference crossinline action2: Raise.() -> B, - @BuilderInference crossinline action3: Raise.() -> C, - @BuilderInference crossinline action4: Raise.() -> D, - @BuilderInference crossinline action5: Raise.() -> E, - @BuilderInference crossinline block: Raise.(A, B, C, D, E) -> F + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + @BuilderInference action5: RaiseAccumulate.() -> E, + block: (A, B, C, D, E) -> F ): F { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - callsInPlace(action5, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - Semigroup.nonEmptyList(), - { mapErrorNel(action1) }, - { mapErrorNel(action2) }, - { mapErrorNel(action3) }, - { mapErrorNel(action4) }, - { mapErrorNel(action5) }, - { x, y, z, u, v -> mapErrorNel { block(x, y, z, u, v) } } - ) + action1, + action2, + action3, + action4, + action5, + {}) { a, b, c, d, e, _ -> + block(a, b, c, d, e) + } } /** @@ -390,32 +326,25 @@ public inline fun Raise>.zipOrAccumulate( */ @RaiseDSL public inline fun Raise>.zipOrAccumulate( - @BuilderInference crossinline action1: Raise.() -> A, - @BuilderInference crossinline action2: Raise.() -> B, - @BuilderInference crossinline action3: Raise.() -> C, - @BuilderInference crossinline action4: Raise.() -> D, - @BuilderInference crossinline action5: Raise.() -> E, - @BuilderInference crossinline action6: Raise.() -> F, - @BuilderInference crossinline block: Raise.(A, B, C, D, E, F) -> G + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + @BuilderInference action5: RaiseAccumulate.() -> E, + @BuilderInference action6: RaiseAccumulate.() -> F, + block: (A, B, C, D, E, F) -> G ): G { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - callsInPlace(action5, InvocationKind.EXACTLY_ONCE) - callsInPlace(action6, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - Semigroup.nonEmptyList(), - { mapErrorNel(action1) }, - { mapErrorNel(action2) }, - { mapErrorNel(action3) }, - { mapErrorNel(action4) }, - { mapErrorNel(action5) }, - { mapErrorNel(action6) }, - { x, y, z, u, v, w -> mapErrorNel { block(x, y, z, u, v, w) } } - ) + action1, + action2, + action3, + action4, + action5, + action6, + {}) { a, b, c, d, e, f, _ -> + block(a, b, c, d, e, f) + } } /** @@ -423,35 +352,27 @@ public inline fun Raise>.zipOrAccumulat */ @RaiseDSL public inline fun Raise>.zipOrAccumulate( - @BuilderInference crossinline action1: Raise.() -> A, - @BuilderInference crossinline action2: Raise.() -> B, - @BuilderInference crossinline action3: Raise.() -> C, - @BuilderInference crossinline action4: Raise.() -> D, - @BuilderInference crossinline action5: Raise.() -> E, - @BuilderInference crossinline action6: Raise.() -> F, - @BuilderInference crossinline action7: Raise.() -> G, - @BuilderInference crossinline block: Raise.(A, B, C, D, E, F, G) -> H + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + @BuilderInference action5: RaiseAccumulate.() -> E, + @BuilderInference action6: RaiseAccumulate.() -> F, + @BuilderInference action7: RaiseAccumulate.() -> G, + block: (A, B, C, D, E, F, G) -> H ): H { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - callsInPlace(action5, InvocationKind.EXACTLY_ONCE) - callsInPlace(action6, InvocationKind.EXACTLY_ONCE) - callsInPlace(action7, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - Semigroup.nonEmptyList(), - { mapErrorNel(action1) }, - { mapErrorNel(action2) }, - { mapErrorNel(action3) }, - { mapErrorNel(action4) }, - { mapErrorNel(action5) }, - { mapErrorNel(action6) }, - { mapErrorNel(action7) }, - { x, y, z, u, v, w, a -> mapErrorNel { block(x, y, z, u, v, w, a) } } - ) + action1, + action2, + action3, + action4, + action5, + action6, + action7, + {}) { a, b, c, d, e, f, g, _ -> + block(a, b, c, d, e, f, g) + } } /** @@ -459,38 +380,29 @@ public inline fun Raise>.zipOrAccumu */ @RaiseDSL public inline fun Raise>.zipOrAccumulate( - @BuilderInference crossinline action1: Raise.() -> A, - @BuilderInference crossinline action2: Raise.() -> B, - @BuilderInference crossinline action3: Raise.() -> C, - @BuilderInference crossinline action4: Raise.() -> D, - @BuilderInference crossinline action5: Raise.() -> E, - @BuilderInference crossinline action6: Raise.() -> F, - @BuilderInference crossinline action7: Raise.() -> G, - @BuilderInference crossinline action8: Raise.() -> H, - @BuilderInference crossinline block: Raise.(A, B, C, D, E, F, G, H) -> I + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + @BuilderInference action5: RaiseAccumulate.() -> E, + @BuilderInference action6: RaiseAccumulate.() -> F, + @BuilderInference action7: RaiseAccumulate.() -> G, + @BuilderInference action8: RaiseAccumulate.() -> H, + block: (A, B, C, D, E, F, G, H) -> I ): I { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - callsInPlace(action5, InvocationKind.EXACTLY_ONCE) - callsInPlace(action6, InvocationKind.EXACTLY_ONCE) - callsInPlace(action7, InvocationKind.EXACTLY_ONCE) - callsInPlace(action8, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - Semigroup.nonEmptyList(), - { mapErrorNel(action1) }, - { mapErrorNel(action2) }, - { mapErrorNel(action3) }, - { mapErrorNel(action4) }, - { mapErrorNel(action5) }, - { mapErrorNel(action6) }, - { mapErrorNel(action7) }, - { mapErrorNel(action8) }, - { x, y, z, u, v, w, a, b -> mapErrorNel { block(x, y, z, u, v, w, a, b) } } - ) + action1, + action2, + action3, + action4, + action5, + action6, + action7, + action8, + {}) { a, b, c, d, e, f, g, h, _ -> + block(a, b, c, d, e, f, g, h) + } } /** @@ -498,83 +410,73 @@ public inline fun Raise>.zipOrAcc */ @RaiseDSL public inline fun Raise>.zipOrAccumulate( - @BuilderInference crossinline action1: Raise.() -> A, - @BuilderInference crossinline action2: Raise.() -> B, - @BuilderInference crossinline action3: Raise.() -> C, - @BuilderInference crossinline action4: Raise.() -> D, - @BuilderInference crossinline action5: Raise.() -> E, - @BuilderInference crossinline action6: Raise.() -> F, - @BuilderInference crossinline action7: Raise.() -> G, - @BuilderInference crossinline action8: Raise.() -> H, - @BuilderInference crossinline action9: Raise.() -> I, - @BuilderInference crossinline block: Raise.(A, B, C, D, E, F, G, H, I) -> J + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + @BuilderInference action5: RaiseAccumulate.() -> E, + @BuilderInference action6: RaiseAccumulate.() -> F, + @BuilderInference action7: RaiseAccumulate.() -> G, + @BuilderInference action8: RaiseAccumulate.() -> H, + @BuilderInference action9: RaiseAccumulate.() -> I, + block: (A, B, C, D, E, F, G, H, I) -> J ): J { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - callsInPlace(action5, InvocationKind.EXACTLY_ONCE) - callsInPlace(action6, InvocationKind.EXACTLY_ONCE) - callsInPlace(action7, InvocationKind.EXACTLY_ONCE) - callsInPlace(action8, InvocationKind.EXACTLY_ONCE) - callsInPlace(action9, InvocationKind.EXACTLY_ONCE) - } - return zipOrAccumulate( - Semigroup.nonEmptyList(), - { mapErrorNel(action1) }, - { mapErrorNel(action2) }, - { mapErrorNel(action3) }, - { mapErrorNel(action4) }, - { mapErrorNel(action5) }, - { mapErrorNel(action6) }, - { mapErrorNel(action7) }, - { mapErrorNel(action8) }, - { mapErrorNel(action9) }, - { x, y, z, u, v, w, a, b, c -> mapErrorNel { block(x, y, z, u, v, w, a, b, c) } } - ) + contract { callsInPlace(block, AT_MOST_ONCE) } + val error: MutableList = mutableListOf() + val a = recover({ action1(RaiseAccumulate(this)) }) { error.addAll(it); EmptyValue } + val b = recover({ action2(RaiseAccumulate(this)) }) { error.addAll(it); EmptyValue } + val c = recover({ action3(RaiseAccumulate(this)) }) { error.addAll(it); EmptyValue } + val d = recover({ action4(RaiseAccumulate(this)) }) { error.addAll(it); EmptyValue } + val e = recover({ action5(RaiseAccumulate(this)) }) { error.addAll(it); EmptyValue } + val f = recover({ action6(RaiseAccumulate(this)) }) { error.addAll(it); EmptyValue } + val g = recover({ action7(RaiseAccumulate(this)) }) { error.addAll(it); EmptyValue } + val h = recover({ action8(RaiseAccumulate(this)) }) { error.addAll(it); EmptyValue } + val i = recover({ action9(RaiseAccumulate(this)) }) { error.addAll(it); EmptyValue } + error.toNonEmptyListOrNull()?.let { raise(it) } + return block(unbox(a), unbox(b), unbox(c), unbox(d), unbox(e), unbox(f), unbox(g), unbox(h), unbox(i)) } /** - * Accumulate the errors obtained by executing the [block] - * over every element of [list] using the given [semigroup]. + * Transform every element of [list] using the given [transform], or accumulate all the occurred errors using [combine]. */ @RaiseDSL public inline fun Raise.mapOrAccumulate( - semigroup: Semigroup<@UnsafeVariance R>, list: Iterable, - @BuilderInference block: Raise.(A) -> B + combine: (R, R) -> R, + @BuilderInference transform: RaiseAccumulate.(A) -> B ): List { - // this could be implemented using [zipOrAccumulate], - // but we can have a faster implementation using [buildList] var error: Any? = EmptyValue - val results = buildList { - list.forEach { - fold({ - block(it) - }, { newError -> - error = semigroup.emptyCombine(error, newError) - }, { - add(it) - }) - } - } - return when (val e = EmptyValue.unbox(error)) { - null -> results - else -> raise(e) + val results = ArrayList(list.collectionSizeOrDefault(10)) + for (item in list) { + fold, B, Unit>( + { transform(RaiseAccumulate(this), item) }, + { errors -> error = combine(error, errors.reduce(combine), combine) }, + { results.add(it) } + ) } + return if (error === EmptyValue) results else raise(unbox(error)) } /** - * Accumulate the errors obtained by executing the [block] - * over every element of [list]. + * Accumulate the errors obtained by executing the [transform] over every element of [list]. */ @RaiseDSL public inline fun Raise>.mapOrAccumulate( list: Iterable, - @BuilderInference crossinline block: Raise.(A) -> B -): List = - mapOrAccumulate(Semigroup.nonEmptyList(), list) { elt -> mapErrorNel { block(elt) } } + @BuilderInference transform: RaiseAccumulate.(A) -> B +): List { + val error = mutableListOf() + val results = ArrayList(list.collectionSizeOrDefault(10)) + for (item in list) { + fold, B, Unit>( + { transform(RaiseAccumulate(this), item) }, + { errors -> error.addAll(errors) }, + { results.add(it) } + ) + } + return error.toNonEmptyListOrNull()?.let { raise(it) } ?: results +} + /** * Receiver type belonging to [mapOrAccumulate]. @@ -583,24 +485,25 @@ public inline fun Raise>.mapOrAccumulate( */ public open class RaiseAccumulate( public val raise: Raise> -): Raise { +) : Raise { @RaiseDSL public override fun raise(r: Error): Nothing = raise.raise(nonEmptyListOf(r)) @RaiseDSL - public fun EitherNel.bindNel(): A = when(this) { + public fun EitherNel.bindNel(): A = when (this) { is Either.Left -> raise.raise(value) is Either.Right -> value } @RaiseDSL - public fun ValidatedNel.bindNel(): A = when(this) { + public fun ValidatedNel.bindNel(): A = when (this) { is Validated.Invalid -> raise.raise(value) is Validated.Valid -> value } + @RaiseDSL public inline fun withNel(block: Raise>.() -> A): A = block(raise) }