From 30f35c655a8b7b8df2b049b84fa2fe29b0ae34c3 Mon Sep 17 00:00:00 2001 From: Jakub Wojnowski <29680262+jwojnowski@users.noreply.github.com> Date: Wed, 17 Apr 2024 17:04:55 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20`flatTapIn`=20and=20`flatTapF?= =?UTF-8?q?`=20to=20`FOptionSyntax`=20and=20`FEitherSyntax`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shared/src/main/scala/mouse/feither.scala | 6 ++++++ shared/src/main/scala/mouse/foption.scala | 6 ++++++ shared/src/test/scala/mouse/FEitherSyntaxTest.scala | 10 ++++++++++ shared/src/test/scala/mouse/FOptionSyntaxTest.scala | 10 ++++++++++ 4 files changed, 32 insertions(+) diff --git a/shared/src/main/scala/mouse/feither.scala b/shared/src/main/scala/mouse/feither.scala index e2f9f54..9aed308 100644 --- a/shared/src/main/scala/mouse/feither.scala +++ b/shared/src/main/scala/mouse/feither.scala @@ -54,6 +54,12 @@ final class FEitherOps[F[_], L, R](private val felr: F[Either[L, R]]) extends An case Right(value) => f(value) } + def flatTapIn[A >: L, B](f: R => Either[A, B])(implicit F: Functor[F]): F[Either[A, R]] = + flatMapIn(value => f(value).map(_ => value)) + + def flatTapF[A >: L, B](f: R => F[Either[A, B]])(implicit F: Monad[F]): F[Either[A, R]] = + flatMapF(value => F.map(f(value))(_.map(_ => value))) + def foldIn[A](left: L => A)(right: R => A)(implicit F: Functor[F]): F[A] = cata(left, right) diff --git a/shared/src/main/scala/mouse/foption.scala b/shared/src/main/scala/mouse/foption.scala index 781d0a7..44e0ebc 100644 --- a/shared/src/main/scala/mouse/foption.scala +++ b/shared/src/main/scala/mouse/foption.scala @@ -73,6 +73,12 @@ final class FOptionOps[F[_], A](private val foa: F[Option[A]]) extends AnyVal { def flatMapF[B](f: A => F[Option[B]])(implicit F: Monad[F]): F[Option[B]] = F.flatMap(foa)(_.fold(F.pure(Option.empty[B]))(f)) + def flatTapIn[B](f: A => Option[B])(implicit F: Functor[F]): F[Option[A]] = + flatMapIn(value => f(value).map(_ => value)) + + def flatTapF[B](f: A => F[Option[B]])(implicit F: Monad[F]): F[Option[A]] = + flatMapF { value => F.map(f(value))(_.map(_ => value)) } + def foldIn[B](default: => B)(f: A => B)(implicit F: Functor[F]): F[B] = cata(default, f) diff --git a/shared/src/test/scala/mouse/FEitherSyntaxTest.scala b/shared/src/test/scala/mouse/FEitherSyntaxTest.scala index 29b2144..e9bd616 100644 --- a/shared/src/test/scala/mouse/FEitherSyntaxTest.scala +++ b/shared/src/test/scala/mouse/FEitherSyntaxTest.scala @@ -57,6 +57,16 @@ class FEitherSyntaxTest extends MouseSuite { assertEquals(leftValue.flatMapF(i => List((i * 2).asRight[String])), leftValue) } + test("FEitherSyntax.flatTapIn") { + assertEquals(rightValue.flatTapIn(i => (i * 2).asRight[String]), List(42.asRight[String])) + assertEquals(leftValue.flatTapIn(i => (i * 2).asRight[String]), leftValue) + } + + test("FEitherSyntax.flatTapF") { + assertEquals(rightValue.flatTapF(i => List((i * 2).asRight[String])), List(42.asRight[String])) + assertEquals(leftValue.flatTapF(i => List((i * 2).asRight[String])), leftValue) + } + test("FEitherSyntax.foldIn") { assertEquals(rightValue.foldIn(_ => 0)(_ => 1), List(1)) assertEquals(leftValue.foldIn(_ => 0)(_ => 1), List(0)) diff --git a/shared/src/test/scala/mouse/FOptionSyntaxTest.scala b/shared/src/test/scala/mouse/FOptionSyntaxTest.scala index d640bb1..b80b102 100644 --- a/shared/src/test/scala/mouse/FOptionSyntaxTest.scala +++ b/shared/src/test/scala/mouse/FOptionSyntaxTest.scala @@ -72,6 +72,16 @@ class FOptionSyntaxTest extends MouseSuite { assertEquals(List(Option.empty[Int]).flatMapF(a => List(Option(a * 2))), List(Option.empty[Int])) } + test("FOptionSyntax.flatTapIn") { + assertEquals(List(Option(1)).flatTapIn(a => Option(a * 2)), List(Option(1))) + assertEquals(List(Option.empty[Int]).flatTapIn(a => Option(a * 2)), List(Option.empty[Int])) + } + + test("FOptionSyntax.flatMapF") { + assertEquals(List(Option(1)).flatTapF(a => List(Option(a * 2))), List(Option(1))) + assertEquals(List(Option.empty[Int]).flatTapF(a => List(Option(a * 2))), List(Option.empty[Int])) + } + test("FOptionSyntax.foldIn") { assertEquals(List(Option(1)).foldIn(false)(_ => true), List(true)) assertEquals(List(Option.empty[Int]).foldIn(false)(_ => true), List(false))