So my project is written in `IO`, and I am now con...
# arrow
s
So my project is written in
IO
, and I am now converting it in
arrow-fx-coroutines
. Thing that I am not able to get my head around is how `IO`’s edge of the world conditions is taken care of if i use
arrow-fx-coroutines
When using
IO
, I was doing like this :
Copy code
sealed class DomainError : Throwable() {
    object NotFound : DomainError()
    object NullInIO : DomainError()

    override fun fillInStackTrace(): Throwable = this
}
and just before sending response to client, I was doing something like :
Copy code
fun IO<DomainResponse>.send(): Unit {
    return this
        .attempt()
        .flatMap { response ->
            when (response) {
                is Either.Left -> { check if it is DomainError and send appropriate response, or else  log the unknown error and send generic 500 internal server error }
                is Either.Right -> { send 200 ok response }
            }
        }
        .suspendCancellable() 
}
By doing something like this I was catching all of the exceptions which wasn’t known to me but were thrown under certain unfortunate scenarios. This kind of approach made me aware of holes in my code, and time to time I went back and fixed them to the point that there are no more surprises. I hoped that
BIO<DomainError, A>
would’ve cleaned up
DomainError
sealed class by not extending Throwable, and still covering me like
IO<Throwable, A>
, but it is reverted. How can I do this with Either ?
Either.catch
gives
Either<Throwable, A>
, and from what I’ve read here, whole point was not to use
Throwable
with
Either
.
j
This seems like an excellent use case for the
handle
function I mentioned earlier.
Copy code
fun (suspend () -> Either<DomainError, DomainResponse>).send(): Unit =
    handle(
        logic = this,
        ifSuccess = { a -> /* send 200 ok response */},
        ifDomainError = { e -> /* send appropriate response for DomainError */},
        ifSystemFailure = { throwable -> /* log the unknown error and send generic 500 internal server error */}
    )
r
The edge of the world is suspend fun main or any suspend function. If you wish to still unsafe run it you can do that through the Platform object
Essentially we are now suspend fully compatible and our own suspend runtime
I think your function above can be a interesting use case to extend a variant of either catch worth exploring and discussing