Hi, does anybody have an idea how to implement the...
# coroutines
k
Hi, does anybody have an idea how to implement the following simple "result monad comprehension" using coroutines, in a better way than what I have come up with so far:?
Copy code
sealed class Result<out T, out E>
class Success<out T>(val value: T) : Result<T, Nothing>()
class Failure<out E>(val error: E) : Result<Nothing, E>()

...

class AccumulatedResultContext<U, E> {
    var lastPartialResult: Result<U, E>? = null
    var continuation: CancellableContinuation<*>? = null

    suspend operator fun <T, F: E> Result<T, F>.not(): T = when(this) {
        is Success -> this.value
        is Failure -> suspendCancellableCoroutine {
            lastPartialResult = this
            continuation = it
        }
    }
}

fun <T, E> accumulateResult(
    block: suspend AccumulatedResultContext<T, E>.() -> Result<T, E>
): Result<T, E> =
    runBlocking {
        val context = AccumulatedResultContext<T, E>()
        launch(start = CoroutineStart.UNDISPATCHED) {
            context.lastPartialResult = block(context)
        }
        if (context.continuation != null) context.continuation!!.cancel()
        context.lastPartialResult!!
    }

...
Copy code
fun mapToUserRecord(
       userSource: UserSoruce
    ): Result<UserRecord.Persisted, ConversionError> = accumulateResult {
        val id = userSource.id
           
        val name = ! validate(userSource.name)

        val description = ! validate(userSource.description)

        Success(UserRecord.Persisted(id, name, description))
    }
Especially, I d like to avoid using the experimental
CoroutineStart.UNDISPATCHED
but it is required when I start nesting
accumulateResult { }
because the execution order of nested coroutines is not guaranteed Thanks for any suggestions