mouse icon indicating copy to clipboard operation
mouse copied to clipboard

Add recover either

Open geirolz opened this issue 1 year ago • 2 comments

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 as or not
  • recoverAsLeft
  • recoverAsRight

geirolz avatar Jul 19 '24 11:07 geirolz

Thank you for your contribution!

However, let me chime in and share my thoughts about some of the PR details please.

  1. MonadError does not seem necessary here. ApplicativeError should be just enough (unless I missed something out).
  2. recoverEither with all the syntax enabled seems to be a shortcut for:
    fa.recoverEither(pf) <=> fa.mapAsRight.recover(pf)
    
    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?
  3. recoverAsRight might seem more sophisticated but in fact it can be expressed with the same two functions but chained in the reverse order:
    fa.recoverAsRight(pf) <=> fa.recover(pf).mapAsRight
    
    But the latter requires less transformations to be applied - is it correct?

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).

satorg avatar Jul 19 '24 23:07 satorg

Thank you @satorg for the detailed review!

  1. MonadError does not seem necessary here. ApplicativeError should be just enough (unless I missed something out).

You are right! Updated the PR

  1. 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

  1. 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)
}

geirolz avatar Jul 20 '24 07:07 geirolz