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 returnfromraiseError
doesn’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 AMtupleN
simon.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