Skip to content

Commit

Permalink
Add accumulate function to IorRaise
Browse files Browse the repository at this point in the history
Used to combine errors into the IorRaise state and trigger
a Both output in a more convenient way. Previously the
only mechanism to do this was to call `bind()` on an `Ior.Both`.
  • Loading branch information
sampengilly committed Apr 24, 2024
1 parent 484c0a2 commit 8b52481
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 1 deletion.
2 changes: 2 additions & 0 deletions arrow-libs/core/arrow-core/api/arrow-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -3429,6 +3429,7 @@ public final class arrow/core/raise/IgnoreErrorsRaise : arrow/core/raise/Raise {

public final class arrow/core/raise/IorRaise : arrow/core/raise/Raise {
public fun <init> (Lkotlin/jvm/functions/Function2;Ljava/util/concurrent/atomic/AtomicReference;Larrow/core/raise/Raise;)V
public final fun accumulate (Ljava/lang/Object;)V
public fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun bind (Larrow/core/Either;)Ljava/lang/Object;
public final fun bind (Larrow/core/Ior;)Ljava/lang/Object;
Expand All @@ -3448,6 +3449,7 @@ public final class arrow/core/raise/IorRaise : arrow/core/raise/Raise {
public fun catch (Larrow/core/continuations/Effect;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun combine (Ljava/lang/Object;)Ljava/lang/Object;
public final fun getCombineError ()Lkotlin/jvm/functions/Function2;
public final fun getOrAccumulate (Larrow/core/Either;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public fun invoke (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun raise (Ljava/lang/Object;)Ljava/lang/Void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ public class ResultRaise(private val raise: Raise<Throwable>) : Raise<Throwable>
recover: (Throwable) -> A,
): A = result(block).fold(
onSuccess = { it },
onFailure = { recover(it) }
onFailure = { recover(it) }
)
}

Expand Down Expand Up @@ -306,6 +306,13 @@ public class IorRaise<Error> @PublishedApi internal constructor(
@PublishedApi
internal fun combine(e: Error): Error = state.updateAndGet { EmptyValue.combine(it, e, combineError) } as Error

@RaiseDSL
public fun accumulate(value: Error): Unit = Ior.Both(value, Unit).bind()

@RaiseDSL
public fun <A> Either<Error, A>.getOrAccumulate(recover: (Error) -> A): A =
fold(ifLeft = { Ior.Both(it, recover(it)) }, ifRight = { Ior.Right(it) }).bind()

@RaiseDSL
@JvmName("bindAllIor")
public fun <A> Iterable<Ior<Error, A>>.bindAll(): List<A> =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package arrow.core.raise

import arrow.core.Either
import arrow.core.Ior
import arrow.core.left
import arrow.core.right
import arrow.core.test.nonEmptyList
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.StringSpec
Expand Down Expand Up @@ -144,4 +146,25 @@ class IorSpec : StringSpec({
one + two + three
} shouldBe Ior.Both("Hi, World", 6)
}

"accumulate combines error and results in Both case" {
ior(String::plus) {
accumulate("nonfatal")
"output"
} shouldBe Ior.Both("nonfatal", "output")
}

"getOrAccumulate on Right outputs value with no change to Ior state" {
ior(String::plus) {
val result = "success".right().getOrAccumulate { "failed" }
"output: $result"
} shouldBe Ior.Right("output: success")
}

"getOrAccumulate on Left combines error and results in Both case with recovered value" {
ior(String::plus) {
val result = "nonfatal".left().getOrAccumulate { "failed" }
"output: $result"
} shouldBe Ior.Both("nonfatal", "output: failed")
}
})

0 comments on commit 8b52481

Please sign in to comment.