package nomisrev import arrow.core.Either import arrow.core.getOrElse import arrow.core.left import arrow.core.raise.Raise import arrow.core.raise.context.either import arrow.core.raise.context.raise import arrow.core.right import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.transform /** * Example 1: * Emitting only success values requires collecting **within** `either { }`, * such that [raise] is used to _cancel_ the `Flow` on typed error. */ context(collector: FlowCollector, _: Raise) suspend fun example(): Unit { repeat(100) { count -> collector.emit(count) } raise("BOOM!") } suspend fun usage1() { val result: Either = either { flow { example() }.collect { println(it) } }.also(::println) } /** * Example 2: * Producing a `Flow` that contains 'Either' such that `raise` **does not** 'cancel' the `Flow`, * */ context(collector: FlowCollector>, _: Raise) suspend fun example2(): Unit { repeat(100) { count -> emit(count) } raise("BOOM!") } suspend fun usage2() { val flow = flow { either { example2() } // Error handling just emits, but we could implement retry logic here .getOrElse { emit(it.left()) } } // alternatively we can implement retry logic here .transform { when(it) { is Either.Left<*> -> emit(1.right()) // retried and success is Either.Right<*> -> emit(it) // Re-emit original } } flow.collect(::println) } context(collector: FlowCollector>) suspend fun emit(a: A): Unit = collector.emit(a.right()) suspend fun main() { usage1() }