Skip to content

Commit

Permalink
Merge pull request #4638 from danicheg/either-syntax
Browse files Browse the repository at this point in the history
Add `EitherOps#leftMapOrKeep` and `EitherOps#leftFlatMapOrKeep`
  • Loading branch information
danicheg authored Jul 23, 2024
2 parents b7d6552 + 1ccfee3 commit aee3702
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 0 deletions.
12 changes: 12 additions & 0 deletions core/src/main/scala/cats/syntax/either.scala
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,12 @@ final class EitherOps[A, B](private val eab: Either[A, B]) extends AnyVal {
case r @ Right(_) => EitherUtil.leftCast(r)
}

def leftMapOrKeep[AA >: A](pf: PartialFunction[A, AA]): Either[AA, B] =
eab match {
case Left(a) => Left(pf.applyOrElse(a, identity[AA]))
case r: Right[A, B] => r
}

@deprecated("Included in the standard library", "2.1.0-RC1")
private[syntax] def flatMap[AA >: A, D](f: B => Either[AA, D]): Either[AA, D] =
eab match {
Expand All @@ -207,6 +213,12 @@ final class EitherOps[A, B](private val eab: Either[A, B]) extends AnyVal {
case r @ Right(_) => EitherUtil.leftCast(r)
}

def leftFlatMapOrKeep[AA >: A, BB >: B](pfa: PartialFunction[A, Either[AA, BB]]): Either[AA, BB] =
eab match {
case l @ Left(a) => pfa.applyOrElse(a, (_: A) => l)
case r: Right[A, B] => r
}

def compare[AA >: A, BB >: B](that: Either[AA, BB])(implicit AA: Order[AA], BB: Order[BB]): Int =
eab match {
case Left(a1) =>
Expand Down
19 changes: 19 additions & 0 deletions tests/shared/src/test/scala/cats/tests/EitherSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,25 @@ class EitherSuite extends CatsSuite {
}
}

test("leftFlatMapOrKeep consistent with leftMapOrKeep") {
forAll { (either: Either[String, Int], pf: PartialFunction[String, String]) =>
val liftedPF: PartialFunction[String, Either[String, Int]] = { case a =>
Either.left[String, Int](pf.applyOrElse(a, identity[String]))
}
assert(either.leftFlatMapOrKeep(liftedPF) === either.leftMapOrKeep(pf))
}
}

test("leftFlatMapOrKeep consistent with swap and then flatMapOrKeep") {
import cats.syntax.monad._

forAll { (either: Either[String, Int], pf: PartialFunction[String, Either[String, Int]]) =>
assert(either.leftFlatMapOrKeep(pf) === either.swap.flatMapOrKeep { case a =>
pf.applyOrElse(a, (_: String) => either).swap
}.swap)
}
}

test("raiseWhen raises when true") {
val result = Either.raiseWhen(true)("ok")
assert(result === Left("ok"))
Expand Down

0 comments on commit aee3702

Please sign in to comment.