Add onError and adaptError to Applicative/MonadError - #1739
Conversation
|
assigning @edmundnoble as well since he is removing |
Codecov Report
@@ Coverage Diff @@
## master #1739 +/- ##
==========================================
+ Coverage 94% 95.27% +1.27%
==========================================
Files 253 265 +12
Lines 4171 4298 +127
Branches 162 99 -63
==========================================
+ Hits 3921 4095 +174
+ Misses 250 203 -47
Continue to review full report at Codecov.
|
|
I'm waiting for #1751 to be resolved to update this PR (probably just moving stuff to |
| F.recoverWith(fa)(pf) | ||
|
|
||
| def onError(fa: F[A])(pf: PartialFunction[E, F[Unit]])(implicit F: ApplicativeError[F, E]): F[A] = | ||
| F.onError(fa)(pf) |
There was a problem hiding this comment.
Yes, I mentioned this in the description :)
Haven't added non-discipline tests (yet?), they all seem to be based on Option, for which none of these two functions happen to make sense
Should I add a more complicated transformer to the tests to test this?
There was a problem hiding this comment.
hmmm, since this is a simple delegation what about adding a simple doctest (maybe using Either) to the method in the type class?
There was a problem hiding this comment.
Bear in mind that tests are missing for the implementation, not just for the syntax. I have added laws and discipline tests, but the reason I still haven't added unit tests is that all the unit tests I could find are based on Option, whereas testing this would require something like
EitherT[Writer, ...., I don't have a problem with it, just wanting to know if it's a good idea
There was a problem hiding this comment.
I assumed that the discipline tests provides enough coverage for the implementation, no? Anyway I am not against adding a EitherT[Writer,... to the unit tests
There was a problem hiding this comment.
Well, my idea was exactly that discipline tests might be enough, which is way I submitted this in its current form. Looking for advice from the maintainers to take the final decision
There was a problem hiding this comment.
yeah, I think @johnynek and I were saying that ideally we also want to cover the delegation in the syntax, and one way to do that easily is to add a doctest in the type class method declaration, which uses the syntax and can also serve as an example in the scala doc.
There was a problem hiding this comment.
I can't see any doctests for the other methods on ApplicativeError, apart from a scaladoc example for fromEither. Would you happen to have an example at hand of how syntax forwarders are tested in cats via doctests ?
There was a problem hiding this comment.
There was a problem hiding this comment.
I'll add these today, especially since there's a bug 😁 (the fa should not be a parameter, shadows the implicit class parameter)
| F.ensureOr(fa)(error)(predicate) | ||
|
|
||
| def adaptError(fa: F[A])(pf: PartialFunction[E, E])(implicit F: MonadError[F, E]): F[A] = | ||
| F.adaptError(fa)(pf) |
|
@edmundnoble @kailuowang @djspiewak Any news on this one? I'm still looking for advice on the testing, but apart from that, this would be nice to have for use with cats-effect IO, now that ApplicativeError seems to be staying in cats. |
| F.attempt(F.fromEither(eab)) <-> F.pure(eab) | ||
|
|
||
| def onErrorPure[A, B](a: A, f: E => F[B]): IsEq[F[A]] = | ||
| F.onError(F.pure(a)){case err => F.void(f(err))} <-> F.pure(a) |
There was a problem hiding this comment.
Not quite sure I follow here, why not def onErrorPure[A, B](a: A, f: E => F[Unit])....? why take a E => F[B]
There was a problem hiding this comment.
I've mentioned this in my comments, I couldn't get a Gen[F[Unit]]. However, it was my first time dealing with all the discipline infrastructure, and never had to to this particular thing in my own experience with scalacheck, so glad to be proven wrong :)
There was a problem hiding this comment.
adding an ArbFU: Arbitrary[F[Unit]] param to the MonadErrorTests and ApplicativeErrorTest methods should do the trick
There was a problem hiding this comment.
I think this is exactly what I did and iirc it didn't compile. Let me give it another try though :)
There was a problem hiding this comment.
compiled for me, EitherTests passes. running full now. update: full suite passed.
There was a problem hiding this comment.
Yes you're right. I hadn't realised I needed to add it to the MonadErrorTests as well (because of parent). Thank you! (I'll update the PR tonight with the change)
There was a problem hiding this comment.
You are welcome. Thank you for contributing!
|
Also I think #1751 is close to merge. I think we can safely assume that |
|
@kailuowang I've simplified the discipline tests to take |
|
👍 LGTM, thanks very much @SystemFw |
|
Merging with two approvals. |
PR:
As per this Gitter conversation with @djspiewak, this PR adds two functions:
ApplicativeError#onError, to execute a callback on certain errors and rethrow:with laws:
Use case: error handling that respects module boundaries, e.g. rollback at the db layer, and then send a failed response at the http layer
MonadError#adaptError, to transform certain errorswith laws:
Use case: transforming errors (especially Throwable) between different layers of an application. The type is not as good as
leftMapbut the best we can have I think (except maybe constraining to Throwable).A few things I'm not sure about code-wise:
syntaximports and trying to adhere to the existing style resulted in fairly "lispy" codeArbitrary[F[Unit]]in the laws, had to settle forF[B].void