recover

inline fun <E, EE, A> Either<E, A>.recover(recover: Raise<EE>.(E) -> A): Either<EE, A>

Recover from any Either.Left if encountered.

The recover DSL allows you to recover from any Either.Left value by:

  • Computing a fallback value A, and resolve the left type E to Nothing.

  • Shifting a new error of type EE into the Either.Left channel.

When providing a fallback value A, the Either.Left type is discarded because the error was handled correctly.

import arrow.core.Either
import arrow.core.recover
import io.kotest.matchers.shouldBe

fun test() {
val error: Either<String, Int> = Either.Left("error")
val fallback: Either<Nothing, Int> = error.recover { it.length }
fallback shouldBe Either.Right(5)
}

When shifting a new error EE into the Either.Left channel, the Either.Left is transformed from E to EE since we shifted a new error.

import arrow.core.Either
import arrow.core.recover
import io.kotest.matchers.shouldBe

fun test() {
val error: Either<String, Int> = Either.Left("error")
val listOfErrors: Either<List<Char>, Int> = error.recover { raise(it.toList()) }
listOfErrors shouldBe Either.Left(listOf('e', 'r', 'r', 'o', 'r'))
}

inline fun <A> Option<A>.recover(recover: SingletonRaise<None>.() -> A): Option<A>

Recover from any None if encountered.

The recover DSL allows you to recover from any None value by:

  • Computing a fallback value A

  • Shifting a new error of None into the Option.

import arrow.core.Option
import arrow.core.none
import arrow.core.Some
import arrow.core.recover
import io.kotest.matchers.shouldBe

fun test() {
val error: Option<Int> = none()
val fallback: Option<Int> = error.recover { 5 }
fallback shouldBe Some(5)
}

When shifting a new error None into the Option:

import arrow.core.Option
import arrow.core.none
import arrow.core.Some
import arrow.core.recover
import io.kotest.matchers.shouldBe

fun test() {
val error: Option<Int> = none()
fun fallback(): Option<Int> = Some(5)
fun failure(): Option<Int> = none()

error.recover { fallback().bind() } shouldBe Some(5)
error.recover { failure().bind() } shouldBe none()
}