From b89c08a615e69e518c6a9e2b31a196897bc42e3e Mon Sep 17 00:00:00 2001 From: zainab-ali Date: Wed, 10 Aug 2016 01:50:40 +0100 Subject: [PATCH 1/3] Adding MonadRec for Kleisli --- core/src/main/scala/cats/data/Kleisli.scala | 47 ++++++++++++++----- .../test/scala/cats/tests/KleisliTests.scala | 17 ++++++- 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/core/src/main/scala/cats/data/Kleisli.scala b/core/src/main/scala/cats/data/Kleisli.scala index 72d509d050..5ff3c47507 100644 --- a/core/src/main/scala/cats/data/Kleisli.scala +++ b/core/src/main/scala/cats/data/Kleisli.scala @@ -180,20 +180,20 @@ private[data] sealed abstract class KleisliInstances3 extends KleisliInstances4 } } -private[data] sealed abstract class KleisliInstances4 { +private[data] sealed abstract class KleisliInstances4 extends KleisliInstances5 { - implicit def catsDataMonadReaderForKleisli[F[_]: Monad, A]: MonadReader[Kleisli[F, A, ?], A] = - new MonadReader[Kleisli[F, A, ?], A] { - def pure[B](x: B): Kleisli[F, A, B] = - Kleisli.pure[F, A, B](x) - - def flatMap[B, C](fa: Kleisli[F, A, B])(f: B => Kleisli[F, A, C]): Kleisli[F, A, C] = - fa.flatMap(f) + implicit def catsDataMonadReaderForKleisli[F[_], A](implicit ev: Monad[F]): MonadReader[Kleisli[F, A, ?], A] = + new KleisliMonadReader[F, A] { + def F0: Monad[F] = ev + } +} - val ask: Kleisli[F, A, A] = Kleisli(Monad[F].pure) +private[data] sealed abstract class KleisliInstances5 { - def local[B](f: A => A)(fa: Kleisli[F, A, B]): Kleisli[F, A, B] = - Kleisli(f.andThen(fa.run)) + implicit def catsDataMonadRecForKleisli[F[_], A](implicit ev0: Monad[F], ev1: MonadRec[F]): MonadRec[Kleisli[F, A, ?]] = + new KleisliMonadRec[F, A] { + def F0: Monad[F] = ev0 + def F1: MonadRec[F] = ev1 } } @@ -283,7 +283,6 @@ private trait KleisliApplicativeError[F[_], A, E] extends KleisliApplicative[F, } - private trait KleisliApplicative[F[_], A] extends Applicative[Kleisli[F, A, ?]] { implicit def F: Applicative[F] @@ -299,3 +298,27 @@ private trait KleisliApplicative[F[_], A] extends Applicative[Kleisli[F, A, ?]] override def product[B, C](fb: Kleisli[F, A, B], fc: Kleisli[F, A, C]): Kleisli[F, A, (B, C)] = Kleisli(a => Applicative[F].product(fb.run(a), fc.run(a))) } + +private trait KleisliMonad[F[_], A] extends Monad[Kleisli[F, A, ?]] { + implicit def F0: Monad[F] + + def pure[B](x: B): Kleisli[F, A, B] = + Kleisli.pure[F, A, B](x) + + def flatMap[B, C](fa: Kleisli[F, A, B])(f: B => Kleisli[F, A, C]): Kleisli[F, A, C] = + fa.flatMap(f) +} + +private trait KleisliMonadReader[F[_], A] extends MonadReader[Kleisli[F, A, ?], A] with KleisliMonad[F, A] { + val ask: Kleisli[F, A, A] = Kleisli(Monad[F].pure) + + def local[B](f: A => A)(fa: Kleisli[F, A, B]): Kleisli[F, A, B] = + Kleisli(f.andThen(fa.run)) +} + +private trait KleisliMonadRec[F[_], A] extends MonadRec[Kleisli[F, A, ?]] with KleisliMonad[F, A] { + implicit def F1: MonadRec[F] + + def tailRecM[B, C](b: B)(f: B => Kleisli[F, A, B Xor C]): Kleisli[F, A, C] = + Kleisli[F, A, C](a => F1.tailRecM[B, C](b)(bb => f(bb).run(a))) +} diff --git a/tests/src/test/scala/cats/tests/KleisliTests.scala b/tests/src/test/scala/cats/tests/KleisliTests.scala index 451a80685c..c9be0ee2d5 100644 --- a/tests/src/test/scala/cats/tests/KleisliTests.scala +++ b/tests/src/test/scala/cats/tests/KleisliTests.scala @@ -103,6 +103,21 @@ class KleisliTests extends CatsSuite { checkAll("SemigroupK[λ[α => Kleisli[Option, α, α]]]", SerializableTests.serializable(catsDataSemigroupKForKleisli)) } + + { + // F has a MonadRec + implicit val F = MonadRec[Option] + + checkAll("Kleisli[Option, Int, Int]", MonadRecTests[Kleisli[Option, Int, ?]].monadRec[Int, Int, Int]) + checkAll("MonadRec[Kleisli[Option, Int, ?]]", SerializableTests.serializable(MonadRec[Kleisli[Option, Int, ?]])) + + Monad[Kleisli[Option, Int, ?]] + FlatMap[Kleisli[Option, Int, ?]] + Applicative[Kleisli[Option, Int, ?]] + Apply[Kleisli[Option, Int, ?]] + Functor[Kleisli[Option, Int, ?]] + } + checkAll("Kleisli[Option, ?, Int]", ContravariantTests[Kleisli[Option, ?, Int]].contravariant[Int, Int, Int]) checkAll("Contravariant[Kleisli[Option, ?, Int]]", SerializableTests.serializable(Contravariant[Kleisli[Option, ?, Int]])) @@ -207,4 +222,4 @@ class KleisliTests extends CatsSuite { FlatMap[IntReader] Semigroup[IntReader[String]] } -} \ No newline at end of file +} From e42b34b8c314f7877c86c9e12cb1737032a21bae Mon Sep 17 00:00:00 2001 From: zainab-ali Date: Wed, 10 Aug 2016 17:50:40 +0100 Subject: [PATCH 2/3] Adding MonadRec instance for Kleisli --- core/src/main/scala/cats/data/Kleisli.scala | 18 +++++++++--------- .../test/scala/cats/tests/KleisliTests.scala | 5 +++++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/core/src/main/scala/cats/data/Kleisli.scala b/core/src/main/scala/cats/data/Kleisli.scala index 5ff3c47507..480cbb339f 100644 --- a/core/src/main/scala/cats/data/Kleisli.scala +++ b/core/src/main/scala/cats/data/Kleisli.scala @@ -182,18 +182,18 @@ private[data] sealed abstract class KleisliInstances3 extends KleisliInstances4 private[data] sealed abstract class KleisliInstances4 extends KleisliInstances5 { - implicit def catsDataMonadReaderForKleisli[F[_], A](implicit ev: Monad[F]): MonadReader[Kleisli[F, A, ?], A] = + implicit def catsDataMonadReaderForKleisli[F[_], A](implicit M: Monad[F]): MonadReader[Kleisli[F, A, ?], A] = new KleisliMonadReader[F, A] { - def F0: Monad[F] = ev + implicit def F: Monad[F] = M } } private[data] sealed abstract class KleisliInstances5 { - implicit def catsDataMonadRecForKleisli[F[_], A](implicit ev0: Monad[F], ev1: MonadRec[F]): MonadRec[Kleisli[F, A, ?]] = + implicit def catsDataMonadRecForKleisli[F[_], A](implicit M: MonadRec[F]): MonadRec[Kleisli[F, A, ?]] = new KleisliMonadRec[F, A] { - def F0: Monad[F] = ev0 - def F1: MonadRec[F] = ev1 + implicit def F: Monad[F] = M + implicit def RF: MonadRec[F] = M } } @@ -300,7 +300,7 @@ private trait KleisliApplicative[F[_], A] extends Applicative[Kleisli[F, A, ?]] } private trait KleisliMonad[F[_], A] extends Monad[Kleisli[F, A, ?]] { - implicit def F0: Monad[F] + implicit def F: Monad[F] def pure[B](x: B): Kleisli[F, A, B] = Kleisli.pure[F, A, B](x) @@ -310,15 +310,15 @@ private trait KleisliMonad[F[_], A] extends Monad[Kleisli[F, A, ?]] { } private trait KleisliMonadReader[F[_], A] extends MonadReader[Kleisli[F, A, ?], A] with KleisliMonad[F, A] { - val ask: Kleisli[F, A, A] = Kleisli(Monad[F].pure) + val ask: Kleisli[F, A, A] = Kleisli(F.pure) def local[B](f: A => A)(fa: Kleisli[F, A, B]): Kleisli[F, A, B] = Kleisli(f.andThen(fa.run)) } private trait KleisliMonadRec[F[_], A] extends MonadRec[Kleisli[F, A, ?]] with KleisliMonad[F, A] { - implicit def F1: MonadRec[F] + implicit def RF: MonadRec[F] def tailRecM[B, C](b: B)(f: B => Kleisli[F, A, B Xor C]): Kleisli[F, A, C] = - Kleisli[F, A, C](a => F1.tailRecM[B, C](b)(bb => f(bb).run(a))) + Kleisli[F, A, C](a => RF.tailRecM[B, C](b)(bb => f(bb).run(a))) } diff --git a/tests/src/test/scala/cats/tests/KleisliTests.scala b/tests/src/test/scala/cats/tests/KleisliTests.scala index c9be0ee2d5..8d28b9e9cc 100644 --- a/tests/src/test/scala/cats/tests/KleisliTests.scala +++ b/tests/src/test/scala/cats/tests/KleisliTests.scala @@ -116,6 +116,7 @@ class KleisliTests extends CatsSuite { Applicative[Kleisli[Option, Int, ?]] Apply[Kleisli[Option, Int, ?]] Functor[Kleisli[Option, Int, ?]] + MonadReader[Kleisli[Option, Int, ?], Int] } checkAll("Kleisli[Option, ?, Int]", ContravariantTests[Kleisli[Option, ?, Int]].contravariant[Int, Int, Int]) @@ -178,6 +179,7 @@ class KleisliTests extends CatsSuite { FlatMap[Kleisli[List, Int, ?]] Semigroup[Kleisli[List, Int, String]] SemigroupK[λ[α => Kleisli[List, α, α]]] + MonadRec[Kleisli[List, Int, ?]] // F is Id Functor[Kleisli[Id, Int, ?]] @@ -194,6 +196,7 @@ class KleisliTests extends CatsSuite { FlatMap[Kleisli[Id, Int, ?]] Semigroup[Kleisli[Id, Int, String]] SemigroupK[λ[α => Kleisli[Id, α, α]]] + MonadRec[Kleisli[Id, Int, ?]] //FIXME - fails to compile // using Reader alias instead of Kleisli with Id as F Functor[Reader[Int, ?]] @@ -210,6 +213,7 @@ class KleisliTests extends CatsSuite { FlatMap[Reader[Int, ?]] Semigroup[Reader[Int, String]] SemigroupK[λ[α => Reader[α, α]]] + MonadRec[Reader[Int, ?]] //FIXME - fails to compile // using IntReader alias instead of Kleisli with Id as F and A as Int type IntReader[A] = Reader[Int, A] @@ -221,5 +225,6 @@ class KleisliTests extends CatsSuite { Monoid[IntReader[String]] FlatMap[IntReader] Semigroup[IntReader[String]] + MonadRec[IntReader] } } From c3f1caed963418c3e4c5e2e66377374b39a0ee9f Mon Sep 17 00:00:00 2001 From: zainab-ali Date: Wed, 10 Aug 2016 18:32:26 +0100 Subject: [PATCH 3/3] Adding MonadRec instance for Kleisli --- tests/src/test/scala/cats/tests/KleisliTests.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/src/test/scala/cats/tests/KleisliTests.scala b/tests/src/test/scala/cats/tests/KleisliTests.scala index 8d28b9e9cc..978362bf12 100644 --- a/tests/src/test/scala/cats/tests/KleisliTests.scala +++ b/tests/src/test/scala/cats/tests/KleisliTests.scala @@ -196,7 +196,6 @@ class KleisliTests extends CatsSuite { FlatMap[Kleisli[Id, Int, ?]] Semigroup[Kleisli[Id, Int, String]] SemigroupK[λ[α => Kleisli[Id, α, α]]] - MonadRec[Kleisli[Id, Int, ?]] //FIXME - fails to compile // using Reader alias instead of Kleisli with Id as F Functor[Reader[Int, ?]] @@ -213,7 +212,6 @@ class KleisliTests extends CatsSuite { FlatMap[Reader[Int, ?]] Semigroup[Reader[Int, String]] SemigroupK[λ[α => Reader[α, α]]] - MonadRec[Reader[Int, ?]] //FIXME - fails to compile // using IntReader alias instead of Kleisli with Id as F and A as Int type IntReader[A] = Reader[Int, A]