diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Either.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Either.kt index 7d6f69ad694..ac775b1586d 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Either.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Either.kt @@ -1344,6 +1344,32 @@ public inline infix fun Either.getOrElse(default: (A) -> B): B { } } +/** + * Returns the right value [B] of this [Either], + * or throws an exception produced by applying the [onLeft] function to the left value [A]. + * + * ```kotlin + * import arrow.core.Either + * import arrow.core.getOrElseThrow + * import io.kotest.assertions.throwables.shouldThrow + * import io.kotest.matchers.shouldBe + * + * fun test() { + * Either.Right(12).getOrElseThrow { RuntimeException("Error: $it") } shouldBe 12 + * shouldThrow { + * Either.Left("error").getOrElseThrow { RuntimeException("Error: $it") } + * }.message shouldBe "Error: error" + * } + * ``` + */ +public inline fun Either.getOrElseThrow(onLeft: (A) -> Throwable): B { + contract { callsInPlace(onLeft, InvocationKind.AT_MOST_ONCE) } + return when (this) { + is Left -> throw onLeft(this.value) + is Right -> this.value + } +} + /** * Returns the value from this [Right] or [Left]. * diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/EitherTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/EitherTest.kt index 8e570bcec97..fa6fae53ff1 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/EitherTest.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/EitherTest.kt @@ -129,6 +129,21 @@ class EitherTest { Left(a).getOrElse { b } shouldBe b } } + + @Test + fun getOrElseThrowOk() = runTest { + checkAll(Arb.int()) { a: Int -> + Right(a).getOrElseThrow { RuntimeException("Error: $it") } shouldBe a + + val left: Either = Left("error") + try { + left.getOrElseThrow { RuntimeException("Error: $it") } + fail("Should have thrown an exception") + } catch (e: RuntimeException) { + e.message shouldBe "Error: error" + } + } + } @Test fun getOrNullOk() = runTest {