Skip to content

Commit

Permalink
Add adaptErr to ApplicativeErrorOps (#2698)
Browse files Browse the repository at this point in the history
* add `adaptErr` to `ApplicativeErrorOps`, make `MonadError#adaptError` an alias for it

* revert changes to ApplicativeErrorLaws/MonadErrorLaws

* replace cross-dependency with duplication
  • Loading branch information
bplommer authored and Luka Jacobowitz committed Feb 5, 2019
1 parent 356e339 commit d3b57b2
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 1 deletion.
6 changes: 5 additions & 1 deletion core/src/main/scala/cats/MonadError.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,13 @@ trait MonadError[F[_], E] extends ApplicativeError[F, E] with Monad[F] {
* scala> 1.asRight[String].adaptError(pf)
* res2: Either[String,Int] = Right(1)
* }}}
*
* The same function is available in `ApplicativeErrorOps` as `adaptErr` - it cannot have the same
* name because this would result in ambiguous implicits. `adaptError` will be moved from MonadError to
* ApplicativeError in Cats 2.0: see [[https://github.com/typelevel/cats/issues/2685]]
*/
def adaptError[A](fa: F[A])(pf: PartialFunction[E, E]): F[A] =
flatMap(attempt(fa))(_.fold(e => raiseError(pf.applyOrElse[E, E](e, _ => e)), pure))
recoverWith(fa)(pf.andThen(raiseError))

/**
* Inverse of `attempt`
Expand Down
27 changes: 27 additions & 0 deletions core/src/main/scala/cats/syntax/applicativeError.scala
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,31 @@ final class ApplicativeErrorOps[F[_], E, A](private val fa: F[A]) extends AnyVal

def orElse(other: => F[A])(implicit F: ApplicativeError[F, E]): F[A] =
F.handleErrorWith(fa)(_ => other)

/**
* Transform certain errors using `pf` and rethrow them.
* Non matching errors and successful values are not affected by this function.
*
* Example:
* {{{
* scala> import cats._, implicits._
*
* scala> def pf: PartialFunction[String, String] = { case "error" => "ERROR" }
*
* scala> "error".asLeft[Int].adaptErr(pf)
* res0: Either[String,Int] = Left(ERROR)
*
* scala> "err".asLeft[Int].adaptErr(pf)
* res1: Either[String,Int] = Left(err)
*
* scala> 1.asRight[String].adaptErr(pf)
* res2: Either[String,Int] = Right(1)
* }}}
*
* This is the same as `MonadErrorOps#adaptError`. It cannot have the same name because
* this would result in ambiguous implicits. `adaptError` will be moved from `MonadError`
* to `ApplicativeError` in Cats 2.0: see [[https://github.com/typelevel/cats/issues/2685]]
*/
def adaptErr(pf: PartialFunction[E, E])(implicit F: ApplicativeError[F, E]): F[A] =
F.recoverWith(fa)(pf.andThen(F.raiseError))
}

0 comments on commit d3b57b2

Please sign in to comment.