From e602fb4e64c15a0984e3d2eab4b7375750afdf47 Mon Sep 17 00:00:00 2001 From: danicheg Date: Sat, 20 Jul 2024 14:45:16 +0400 Subject: [PATCH 1/4] Add EitherOps#leftMapOrKeep --- core/src/main/scala/cats/syntax/either.scala | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/src/main/scala/cats/syntax/either.scala b/core/src/main/scala/cats/syntax/either.scala index a4361545c0..2b6e7a8944 100644 --- a/core/src/main/scala/cats/syntax/either.scala +++ b/core/src/main/scala/cats/syntax/either.scala @@ -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(_) => 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 { From 03c055e8407a803b4d622b591fd07d28731dccd1 Mon Sep 17 00:00:00 2001 From: danicheg Date: Sat, 20 Jul 2024 15:18:36 +0400 Subject: [PATCH 2/4] Add EitherOps#leftFlatMapOrKeep --- core/src/main/scala/cats/syntax/either.scala | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/src/main/scala/cats/syntax/either.scala b/core/src/main/scala/cats/syntax/either.scala index 2b6e7a8944..ae29d45c9b 100644 --- a/core/src/main/scala/cats/syntax/either.scala +++ b/core/src/main/scala/cats/syntax/either.scala @@ -213,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(_) => r + } + def compare[AA >: A, BB >: B](that: Either[AA, BB])(implicit AA: Order[AA], BB: Order[BB]): Int = eab match { case Left(a1) => From 5d74ad532bdeca0c4885718a00aa842d20c64c10 Mon Sep 17 00:00:00 2001 From: danicheg Date: Sat, 20 Jul 2024 15:53:10 +0400 Subject: [PATCH 3/4] Add tests for leftMapOrKeep & leftFlatMapOrKeep --- .../test/scala/cats/tests/EitherSuite.scala | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/shared/src/test/scala/cats/tests/EitherSuite.scala b/tests/shared/src/test/scala/cats/tests/EitherSuite.scala index eca7b226e7..3d0e6cac73 100644 --- a/tests/shared/src/test/scala/cats/tests/EitherSuite.scala +++ b/tests/shared/src/test/scala/cats/tests/EitherSuite.scala @@ -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")) From 1ccfee329c486e7e8b5a685d0f8a311767bd1d97 Mon Sep 17 00:00:00 2001 From: danicheg Date: Sun, 21 Jul 2024 15:17:26 +0400 Subject: [PATCH 4/4] Tweak the case in patmat --- core/src/main/scala/cats/syntax/either.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/main/scala/cats/syntax/either.scala b/core/src/main/scala/cats/syntax/either.scala index ae29d45c9b..4c1ca96015 100644 --- a/core/src/main/scala/cats/syntax/either.scala +++ b/core/src/main/scala/cats/syntax/either.scala @@ -196,8 +196,8 @@ final class EitherOps[A, B](private val eab: Either[A, B]) extends AnyVal { 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(_) => r + 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") @@ -215,8 +215,8 @@ final class EitherOps[A, B](private val eab: Either[A, B]) extends AnyVal { 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(_) => r + 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 =