bind

open suspend fun <B> Effect<R, B>.bind(): B
open suspend fun <B> EagerEffect<R, B>.bind(): B
open fun <A> EagerEffect<R, A>.bind(): A
open suspend fun <A> Effect<R, A>.bind(): A
open fun <A> Validated<R, A>.bind(): A


open fun <A> Either<R, A>.bind(): A

Extract the Either.Right value of an Either. Any encountered Either.Left will be raised as a logical failure in this Raise context. You can wrap the bind call in recover if you want to attempt to recover from any logical failure.

fun test() {
val one: Either<Nothing, Int> = 1.right()
val left: Either<String, Int> = Either.Left("failed")

either {
val x = one.bind()
val y = recover({ left.bind() }) { failure : String -> 1 }
x + y
} shouldBe Either.Right(2)
}

open fun <A> Result<A>.bind(transform: (Throwable) -> R): A

Extract the Result.success value out of Result, because Result works with Throwable as its error type you need to transform to R.

Note that this functions can currently not be inline without Context Receivers, and thus doesn't allow suspension in its error handler. To do so, use Result.recover and bind.

suspend fun test() {
val one: Result<Int> = Result.success(1)
val failure: Result<Int> = Result.failure(RuntimeException("Boom!"))

either {
val x = one.bind { -1 }
val y = failure.bind { failure: Throwable ->
raise("Something bad happened: ${failure.message}")
}
val z = failure.recover { failure: Throwable ->
delay(10)
1
}.bind { raise("Something bad happened: ${it.message}") }
x + y + z
} shouldBe Either.Left("Something bad happened: Boom!")
}

open fun <A> Option<A>.bind(transform: Raise<R>.(None) -> A): A

Extract the Some value out of Option, because Option works with None as its error type you need to transform to R.

Note that this functions can currently not be inline without Context Receivers, and thus doesn't allow suspension in its error handler. To do so, use Option.recover and bind.

suspend fun test() {
val empty: Option<Int> = None
either {
val x: Int = empty.bind { _: None -> 1 }
val y: Int = empty.bind { _: None -> raise("Something bad happened: Boom!") }
val z: Int = empty.recover { _: None ->
delay(10)
1
}.bind { raise("Something bad happened: Boom!") }
x + y + z
} shouldBe Either.Left("Something bad happened: Boom!")
}