commonMain.OutcomeComprehension.kt Maven / Gradle / Ivy
The newest version!
package no.dossier.libraries.functional
import kotlinx.coroutines.*
import kotlin.coroutines.CoroutineContext
/**
* This is a context object used as a receiver of the [composeOutcome] function. It carries a
* CoroutineContext instance so that we can launch child coroutines in that block, and also it carries a reference
* to [failureSetter] so that the latest partial result can be captured in case of [Failure].
*/
class AccumulatedResultContext(
override val coroutineContext: CoroutineContext,
private val failureSetter: (failure: Failure) -> Unit
) : CoroutineScope {
suspend operator fun Outcome.component1(): T = this.bind()
suspend operator fun Outcome.not(): T = this.bind()
suspend fun Outcome.bind(): T = this.resolve {
failureSetter(it)
coroutineScope { cancel() }
awaitCancellation()
}
}
/**
* Attempts to compose an instance of [Outcome] by evaluating a set of partial results.
* This emulates monad comprehensions by controlling flow via coroutines.
*
* Expressions inside the *block* lambda returning Outcome are supposed to be bound via *!* operator function
* so that they either return the Success value of T, or in case of Failure the whole block is interrupted
* and that specific partial Failure result is returned from the whole [composeOutcome] block.
*
* This a simple coroutine-based implementation of Result/Outcome/Either monad comprehension inspired by Arrow library.
*
* @param E Error type
* @param T Success type
*/
fun composeOutcome(
block: suspend AccumulatedResultContext.() -> Outcome
): Outcome = runBlocking {
lateinit var outcome: Outcome
val failureSetter: (failure: Failure) -> Unit = { outcome = it }
coroutineScope {
launch {
outcome = block(AccumulatedResultContext(coroutineContext, failureSetter))
}
}
outcome
}
/**
* @see composeOutcome
* @param E Error type
* @param T Success type
*/
@Deprecated("This function was renamed", ReplaceWith("composeOutcome(block)"))
fun attemptBuildResult(
block: suspend AccumulatedResultContext.() -> Outcome
): Outcome = composeOutcome(block)
© 2015 - 2024 Weber Informatics LLC | Privacy Policy