Sam Pengilly
01/27/2023, 5:15 AMsuspend fun <T> someFunc(
retryPolicy: Schedule<...>,
parse: EffectScope<Throwable>.(res: Response) -> T
) = either {
val response = retryPolicy.retry { someThrowingCode() }
parse(response)
}
I would expect that any NonFatal
exception raised within the either {}
block would get captured by the underlying DefaultEffect
and recovered to a Left
.
However in a unit test to confirm this behaviour the exception is raised to the test itself and fails the test before someFunc
returnsattempt {} catch {}
comes in? I’m just now seeing thatsuspend fun someFunc(...) = either {
val a = runCatching { someThrowingCode() }.bind { it }
// do something with a
}
Using attempt {} catch {}
and manually calling shift()
didn’t seem to change anythingEither.catch {}
in place of runCatching {}
Stylianos Gakis
01/27/2023, 8:45 AMSam Pengilly
01/27/2023, 8:55 AMeither {}
is just an alias for effect {}.toEither()
I would have thought that the underlying functionality would automatically capture an exception thrown in the effect as Left
in the toEither()
callsimon.vergauwen
01/27/2023, 9:00 AMThrowable
is not automatically captured by EffectScope<Throwable>
you need to explicitly capture it. You're best bet is to use Either.catch { }
and then call bind
on it.
runCatching
vs Either.catch
the latter doesn't capture Fatal
exceptions or CancellationException
. This is because Result
was build for Continuation
internals, and Either
was build for application development.
So you probably want to wrap retryPolicy.retry
in Either.catch
here.
attempt { } catch { }
exists, but that works over typed errors only atm. We're still designing DSL shaped operators for this in 2.x.x.
I am hoping to backport them to 1.2.x soon, and share a PR here for gathering feedback. Here is the design in 2.x.x. All functions from this point and below, https://github.com/arrow-kt/arrow/blob/arrow-2/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/Raise.kt#L211.
Any earlier feedback would be greatly appreciated 🙏 Hope this helps ☺️Sam Pengilly
01/27/2023, 9:05 AMEffect
automatically?
I was thrown off today as it seemed like the signatures for this were already there in 1.x, with fold
being used and DefaultEffect
having a catch(Throwable) {}
block internallysimon.vergauwen
01/27/2023, 9:07 AMEffect.fold
when consuming it at the edge. So when calling fold
on Effect<E, A>
you can recover to B
from E
, Throwable
and A
.