Add recover either
Add methods to AnyF to recover errors to Either where an instance of MonadError[F] is provided.
New methods:
- recoverEither // not sure if put the
asor not - recoverAsLeft
- recoverAsRight
Thank you for your contribution!
However, let me chime in and share my thoughts about some of the PR details please.
MonadErrordoes not seem necessary here.ApplicativeErrorshould be just enough (unless I missed something out).recoverEitherwith all the syntax enabled seems to be a shortcut for:
I wonder is there a benefit from introducing a function that can be represented as a chain of other two existing functions without adding any new functionality of its own?fa.recoverEither(pf) <=> fa.mapAsRight.recover(pf)recoverAsRightmight seem more sophisticated but in fact it can be expressed with the same two functions but chained in the reverse order:
But the latter requires less transformations to be applied - is it correct?fa.recoverAsRight(pf) <=> fa.recover(pf).mapAsRight
Note that I cannot find a simple replacement for recoverAsLeft. Therefore it looks like the most worthwhile addition to me (even though it could be a quite narrow use case).
Thank you @satorg for the detailed review!
- MonadError does not seem necessary here. ApplicativeError should be just enough (unless I missed something out).
You are right! Updated the PR
- recoverEither with all the syntax enabled seems to be a shortcut
Right, I added it for completeness mainly - the true need was just recoverAsLeft. Btw many operators implementation are just shortcut so I wouldn't care to much about it. The scope of mouse is to provide a more easily and convenient syntax
- recoverAsRight might seem more sophisticated but in fact it can be expressed with the same two functions but chained in the reverse order.
Didn't notice that - you are right!
recoverAsLeft is the main reason for this PR. Happens that you have an effect that contains the errors, some of them are failures for you and you want to move them in the left branch of the Either.
In this way is like an attempt but only for some cases defined by the partial function.
val ioa: IO[Unit] = ???
ioa.recoverAsLeft {
case ex: MyLogicalFailure => ex
}
// or when you have to lift to Either only some errors and map them basically
// In this case the errors not mapped will raise an exception and will be treated as 500 ( internal server error ) - the others // are properly treated with different error codes
ioa.recoverAsLeft {
case ex: MyLogicalFailure => HttpError(400, ex.getMessage)
}