Gopal S Akshintala
03/19/2020, 1:09 AMApplicative) + lazy call functions (with BIO.defer), so when mapN processes from left to right, first raiseError should halt the processing and rest of the functions shouldn’t be called, @pakoito helped me come-up with this approach, but I am facing 2 problems:
1. I am using BIO, but raiseError from ApplicativeError doesn’t return a Kind2, how can I get around it?
2. IO.defer{..} has this compiler error: Type mismatch. Required: () → IOOf<String, ???> Found: () → Unit for both my extension functions raiseAnError() and justString()
Please help. Thanks.
@Test
fun `IO ApplicativeError 2`() {
val product =
IO.applicativeError<String>().mapN(
IO.defer { raiseSomeError() },
IO.defer { justString() }
) {}.fix().unsafeRunSyncEither()
product.fold({ assertEquals("error", it) }, {})
}
private fun <S> ApplicativeError<S, String>.raiseSomeError(): Kind2<S, String, Unit> {
println("raising an error")
return raiseError("error")
}
private fun <S> ApplicativeError<S, String>.justString(): Kind2<S, String, Unit> {
println("This should not be printed")
return just("just")
}simon.vergauwen
03/19/2020, 8:40 AMI am using BIO, butThat is correct, but you don’t need it to returnfromraiseErrordoesn’t return aApplicativeError, how can I get around it?Kind2
Kind2.
private fun <S> ApplicativeError<S, String>.raiseSomeError(): Kind<S, Unit> {
println("raising an error")
return raiseError("error")
}
Should work just fine with BIO, your error is fixed to “String” here. Calling this function for BIO will return Kind<IOPartialOf<String>, Unit> so it returns Kind2 when you use it with BIO.
S = IOPartialOf<String> in this case.
And the same principle applies for justString().Gopal S Akshintala
03/19/2020, 9:23 AMGopal S Akshintala
03/19/2020, 9:23 AM@Test
fun `IO ApplicativeError 2`() {
val product =
IO.applicativeError<IOPartialOf<String>>().mapN(
IO.defer { raiseSomeError() },
IO.defer { justString() }
) {}.fix().unsafeRunSyncEither()
product.fold({ assertEquals("error", it) }, {})
}
private fun <S> ApplicativeError<S, String>.raiseSomeError(): Kind<S, Unit> {
println("raising an error")
return raiseError("error")
}
private fun <S> ApplicativeError<S, String>.justString(): Kind<S, String> {
println("This should not be printed")
return just("just")
}Gopal S Akshintala
03/19/2020, 9:24 AMsimon.vergauwen
03/19/2020, 9:25 AMrelease/0.11.0.
Your mapN lambda is empty.Gopal S Akshintala
03/19/2020, 9:26 AMGopal S Akshintala
03/19/2020, 9:26 AMtupleNsimon.vergauwen
03/19/2020, 9:38 AMApplicativeError instance for BIO still has E fixed to Throwable, and not parameterised over E. That’s why you saw that weird behavior 🙂 This snippet works fine.
BIO is still WIP, especially the final touches like this.simon.vergauwen
03/19/2020, 9:38 AMGopal S Akshintala
03/19/2020, 10:13 AMsimon.vergauwen
03/19/2020, 10:13 AM0.10.5-SNAPSHOT since there IO can only provide an instance fixed to Throwable.simon.vergauwen
03/19/2020, 10:16 AMBIO and its API are very welcome :)simon.vergauwen
03/19/2020, 10:16 AMGopal S Akshintala
03/19/2020, 10:17 AMGopal S Akshintala
03/19/2020, 11:30 AM@Test
fun `Either ApplicativeError`() {
val product = Either.applicativeError<String>().run {
tupledN(
raiseSomeError() ,
justString()
)
}.fix()
product.fold({ assertEquals("error", it) }, {})
}Gopal S Akshintala
03/19/2020, 11:30 AMsimon.vergauwen
03/19/2020, 11:40 AMGopal S Akshintala
03/19/2020, 11:40 AMGopal S Akshintala
03/19/2020, 11:42 AMGopal S Akshintala
03/19/2020, 12:19 PMGopal S Akshintala
03/19/2020, 12:42 PM<http://IO.de|IO.de>fer{}Gopal S Akshintala
03/19/2020, 12:42 PMsimon.vergauwen
03/19/2020, 1:08 PMEither doesn’t have the power to defer execution like IO canGopal S Akshintala
03/19/2020, 1:09 PMsimon.vergauwen
03/19/2020, 1:11 PMMonadDefer such as Eval or IO or something similarGopal S Akshintala
03/20/2020, 4:38 AMMonadDefer + EitherApplicativeError/ValidatedApplicativeError, just like IO (MonadDefer + IOApplicativeError). Otherwise the example [here](https://next.arrow-kt.io/docs/patterns/error_handling/#example--alternative-validation-strategies-using-applicativeerror) has a serious flaw, where all methods are called in failFast as well (Cc: @raulraja), which prevents using this approach in Prod. I tried desperately to mix both IO.monadDefer() and Either.applicativeError() but in vain 😞simon.vergauwen
03/20/2020, 9:50 AMBIO?simon.vergauwen
03/20/2020, 9:50 AMBIO is IO + Either it should serve your exact needssimon.vergauwen
03/20/2020, 9:51 AMEitherT<ForIO, E, A> at a penalty of wrapping for syntax.simon.vergauwen
03/20/2020, 9:53 AMIO errors, you can take a look at Ank which is the tool we use to validate our KDoc code snippets. It collects all the snippets and compiles without failing fast, that way we can output all the snippets/files that are broken instead of failing fast at the first broken snippet.
Beside that IO already has the capabilities to fail-fast just like Either does.simon.vergauwen
03/20/2020, 9:56 AMBIO you can use Throwable to model your Left side. Which causes fail-fast to happen in IO, this is also possible with a sealed class hierarchy if desired. However BIO will allow you to remove the Throwable constraint, and that will allow you to work with BIO as if it’s suspend () -> Either<E, A>.
class DomainError : Throwable() {
override fun fillInStackTrace(): Throwable = this
}Gopal S Akshintala
03/20/2020, 9:58 AMsimon.vergauwen
03/20/2020, 10:06 AMSwitch strategies (FailFast/Accumulation) for same codeI’d have to take a look how we can implement it should be possible and it’s a feature I’d like to have in Arrow Fx since it’s something a lot of people want/need out-of-the-box for doing validation over effects like db or network results.
simon.vergauwen
03/20/2020, 10:07 AMFailFast doesn’t call subsequent methods on first error
IO already does this for Throwable, and BIO does it for both E and Throwable so this is already achieved by both.Gopal S Akshintala
03/20/2020, 11:20 AMI’d have to take a look how we can implement it should be possible and it’s a feature I’d like to have in Arrow Fx since it’s something a lot of people want/need out-of-the-box for doing validation over effects like db or network results.Thanks @simon.vergauwen I shall be eagerly waiting for this, to address my [requirement](https://github.com/overfullstack/ad-hoc-poly/blob/0093fa5c9a7c90790f5d353b2970bdae298757cd/validation-templates/src/main/kotlin/com/validation/rules/UserRules.kt#L35)
simon.vergauwen
03/20/2020, 11:51 AMAccumulation strategy to EffectValidator and then we could include it in Arrow Fx if we want or at least in the documentation as a reference 🙂Gopal S Akshintala
03/20/2020, 11:52 AMGopal S Akshintala
03/22/2020, 7:17 AM