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 returnsSam Pengilly
01/27/2023, 5:18 AMattempt {} catch {} comes in? I’m just now seeing thatSam Pengilly
01/27/2023, 5:35 AMsuspend 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 anythingSam Pengilly
01/27/2023, 5:37 AMEither.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 internallySam Pengilly
01/27/2023, 9:06 AMsimon.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.