From 0f3b16ca0a68f2af95b5811d26992ab6d9f2ea12 Mon Sep 17 00:00:00 2001 From: Filippo Mariotti Date: Sat, 3 Mar 2018 20:29:01 +0000 Subject: [PATCH 01/16] Added foldLeft and foldRight to WriterT and Foldable instance --- core/src/main/scala/cats/data/WriterT.scala | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index 95620f4cac..b91bff1cd8 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -1,8 +1,8 @@ package cats package data +import cats.Foldable import cats.kernel.instances.tuple._ - import cats.kernel.CommutativeMonoid import cats.syntax.semigroup._ @@ -63,6 +63,12 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) { mapWritten(_ => monoidL.empty) def show(implicit F: Show[F[(L, V)]]): String = F.show(run) + + def foldLeft[C](c: C)(f: (C, V) => C)(implicit F: Foldable[F]): C = + F.foldLeft(run, c)((z, v) => f(z, v._2)) + + def foldRight[C](lc: Eval[C])(f: (V, Eval[C]) => Eval[C])(implicit F: Foldable[F]): Eval[C] = + F.foldRight(run, lc)((v, z) => f(v._2, z)) } object WriterT extends WriterTInstances with WriterTFunctions { @@ -134,6 +140,11 @@ private[data] sealed abstract class WriterTInstances0 extends WriterTInstances1 implicit def catsDataMonoidForWriterTId[L:Monoid, V:Monoid]: Monoid[WriterT[Id, L, V]] = catsDataMonoidForWriterT[Id, L, V] + + implicit def catsDataFoldableForWriterT[F[_], L, V](implicit F: Foldable[F]): Foldable[WriterT[F, L, ?]] = + new WriterTFoldable[F, L]{ + val F0: Foldable[F] = F + } } private[data] sealed abstract class WriterTInstances1 extends WriterTInstances2 { @@ -410,6 +421,13 @@ private[data] sealed trait WriterTCoflatMap[F[_], L] extends CoflatMap[WriterT[F def coflatMap[A, B](fa: WriterT[F, L, A])(f: WriterT[F, L, A] => B): WriterT[F, L, B] = fa.map(_ => f(fa)) } +private[data] sealed trait WriterTFoldable[F[_], L] extends Foldable[WriterT[F, L, ?]] { + + implicit def F0: Foldable[F] + + def foldLeft[A, B](fa: WriterT[F, L, A], b: B)(f: (B, A) => B): B = fa.foldLeft(b)(f) + def foldRight[A, B](fa: WriterT[F, L, A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = fa.foldRight(lb)(f) +} private[data] trait WriterTFunctions { def putT[F[_], L, V](vf: F[V])(l: L)(implicit functorF: Functor[F]): WriterT[F, L, V] = From 4d1d7f7c08c81e1a61a14c3efcbcb036c760971d Mon Sep 17 00:00:00 2001 From: Filippo Mariotti Date: Sat, 3 Mar 2018 23:59:33 +0000 Subject: [PATCH 02/16] Added tests for Foldable instance --- tests/src/test/scala/cats/tests/WriterTSuite.scala | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/src/test/scala/cats/tests/WriterTSuite.scala b/tests/src/test/scala/cats/tests/WriterTSuite.scala index 255da35c5a..7836be91ac 100644 --- a/tests/src/test/scala/cats/tests/WriterTSuite.scala +++ b/tests/src/test/scala/cats/tests/WriterTSuite.scala @@ -370,6 +370,15 @@ class WriterTSuite extends CatsSuite { checkAll("ContravariantMonoidal[WriterT[Const[String, ?], Int, ?]]", SerializableTests.serializable(ContravariantMonoidal[WriterT[Const[String, ?], Int, ?]])) } + { + // F has a Foldable and L has a Monoid + implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monoid[Int] + Foldable[WriterT[Const[String, ?], Int, ?]] + + checkAll("WriterT[Const[String, ?], ListWrapper[Int], ?]", FoldableTests[WriterT[Const[String, ?], ListWrapper[Int], ?]].foldable[Int, Int]) + checkAll("Foldable[WriterT[Const[String, ?], ListWrapper[Int], ?]]", SerializableTests.serializable(Foldable[WriterT[Const[String, ?], ListWrapper[Int], ?]])) + } + checkAll("WriterT[Option, Int, ?]", CommutativeMonadTests[WriterT[Option, Int, ?]].commutativeMonad[Int, Int, Int]) checkAll("CommutativeMonad[WriterT[Option, Int, ?]]",SerializableTests.serializable(CommutativeMonad[WriterT[Option, Int, ?]])) } From 241f2131a36bcaea641c530661eed9efdb3d44ef Mon Sep 17 00:00:00 2001 From: Filippo Mariotti Date: Sun, 4 Mar 2018 19:05:06 +0000 Subject: [PATCH 03/16] Added traverse. Fixed priority of the implicit search for isntances --- core/src/main/scala/cats/data/WriterT.scala | 46 ++++++++++++++------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index b91bff1cd8..f78c2e42be 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -69,6 +69,8 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) { def foldRight[C](lc: Eval[C])(f: (V, Eval[C]) => Eval[C])(implicit F: Foldable[F]): Eval[C] = F.foldRight(run, lc)((v, z) => f(v._2, z)) + + def traverse[G[_], V1](f: V => G[V1])(implicit F: Traverse[F], G: Applicative[G]): G[WriterT[F, L, V1]] = ??? } object WriterT extends WriterTInstances with WriterTFunctions { @@ -101,9 +103,21 @@ private[data] sealed abstract class WriterTInstances extends WriterTInstances0 { implicit val F0: Monad[F] = F implicit val L0: Monoid[L] = L } + + implicit def catsDataFoldableForWriterT[F[_], L, V](implicit F: Foldable[F]): Foldable[WriterT[F, L, ?]] = + new WriterTFoldable[F, L]{ + val F0: Foldable[F] = F + } } private[data] sealed abstract class WriterTInstances0 extends WriterTInstances1 { + implicit def catsDataTraverseForWriterT[F[_], L, V](implicit F: Traverse[F]): Traverse[WriterT[F, L, ?]] = + new WriterTTraverse[F, L] { + val F0: Traverse[F] = F + } +} + +private[data] sealed abstract class WriterTInstances1 extends WriterTInstances2 { implicit def catsDataMonadErrorForWriterT[F[_], L, E](implicit F: MonadError[F, E], L: Monoid[L]): MonadError[WriterT[F, L, ?], E] = new WriterTMonadError[F, L, E] { implicit val F0: MonadError[F, E] = F @@ -140,14 +154,9 @@ private[data] sealed abstract class WriterTInstances0 extends WriterTInstances1 implicit def catsDataMonoidForWriterTId[L:Monoid, V:Monoid]: Monoid[WriterT[Id, L, V]] = catsDataMonoidForWriterT[Id, L, V] - - implicit def catsDataFoldableForWriterT[F[_], L, V](implicit F: Foldable[F]): Foldable[WriterT[F, L, ?]] = - new WriterTFoldable[F, L]{ - val F0: Foldable[F] = F - } } -private[data] sealed abstract class WriterTInstances1 extends WriterTInstances2 { +private[data] sealed abstract class WriterTInstances2 extends WriterTInstances3 { implicit def catsDataMonadForWriterTId[L:Monoid]: Monad[WriterT[Id, L, ?]] = catsDataMonadForWriterT[Id, L] @@ -158,7 +167,7 @@ private[data] sealed abstract class WriterTInstances1 extends WriterTInstances2 catsDataSemigroupForWriterT[Id, L, V] } -private[data] sealed abstract class WriterTInstances2 extends WriterTInstances3 { +private[data] sealed abstract class WriterTInstances3 extends WriterTInstances4 { implicit def catsDataMonadForWriterT[F[_], L](implicit F: Monad[F], L: Monoid[L]): Monad[WriterT[F, L, ?]] = new WriterTMonad[F, L] { implicit val F0: Monad[F] = F @@ -174,12 +183,12 @@ private[data] sealed abstract class WriterTInstances2 extends WriterTInstances3 catsDataCoflatMapForWriterT[Id, L] } -private[data] sealed abstract class WriterTInstances3 extends WriterTInstances4 { +private[data] sealed abstract class WriterTInstances4 extends WriterTInstances5 { implicit def catsDataFlatMapForWriterTId[L:Semigroup]: FlatMap[WriterT[Id, L, ?]] = catsDataFlatMapForWriterT2[Id, L] } -private[data] sealed abstract class WriterTInstances4 extends WriterTInstances5 { +private[data] sealed abstract class WriterTInstances5 extends WriterTInstances6 { implicit def catsDataFlatMapForWriterT1[F[_], L](implicit F: FlatMap[F], L: Monoid[L]): FlatMap[WriterT[F, L, ?]] = new WriterTFlatMap1[F, L] { implicit val F0: FlatMap[F] = F @@ -192,7 +201,7 @@ private[data] sealed abstract class WriterTInstances4 extends WriterTInstances5 } } -private[data] sealed abstract class WriterTInstances5 extends WriterTInstances6 { +private[data] sealed abstract class WriterTInstances6 extends WriterTInstances7 { implicit def catsDataApplicativeErrorForWriterT[F[_], L, E](implicit F: ApplicativeError[F, E], L: Monoid[L]): ApplicativeError[WriterT[F, L, ?], E] = new WriterTApplicativeError[F, L, E] { implicit val F0: ApplicativeError[F, E] = F @@ -200,7 +209,7 @@ private[data] sealed abstract class WriterTInstances5 extends WriterTInstances6 } } -private[data] sealed abstract class WriterTInstances6 extends WriterTInstances7 { +private[data] sealed abstract class WriterTInstances7 extends WriterTInstances8 { implicit def catsDataAlternativeForWriterT[F[_], L](implicit F: Alternative[F], L: Monoid[L]): Alternative[WriterT[F, L, ?]] = new WriterTAlternative[F, L] { implicit val F0: Alternative[F] = F @@ -213,7 +222,7 @@ private[data] sealed abstract class WriterTInstances6 extends WriterTInstances7 } } -private[data] sealed abstract class WriterTInstances7 extends WriterTInstances8 { +private[data] sealed abstract class WriterTInstances8 extends WriterTInstances9 { implicit def catsDataMonoidKForWriterT[F[_], L](implicit F: MonoidK[F]): MonoidK[WriterT[F, L, ?]] = new WriterTMonoidK[F, L] { implicit val F0: MonoidK[F] = F @@ -230,7 +239,7 @@ private[data] sealed abstract class WriterTInstances7 extends WriterTInstances8 } } -private[data] sealed abstract class WriterTInstances8 extends WriterTInstances9 { +private[data] sealed abstract class WriterTInstances9 extends WriterTInstances10 { implicit def catsDataSemigroupKForWriterT[F[_], L](implicit F: SemigroupK[F]): SemigroupK[WriterT[F, L, ?]] = new WriterTSemigroupK[F, L] { implicit val F0: SemigroupK[F] = F @@ -244,7 +253,7 @@ private[data] sealed abstract class WriterTInstances8 extends WriterTInstances9 } -private[data] sealed abstract class WriterTInstances9 extends WriterTInstances10 { +private[data] sealed abstract class WriterTInstances10 extends WriterTInstances11 { implicit def catsDataApplyForWriterT[F[_], L](implicit F: Apply[F], L: Semigroup[L]): Apply[WriterT[F, L, ?]] = new WriterTApply[F, L] { implicit val F0: Apply[F] = F @@ -252,7 +261,7 @@ private[data] sealed abstract class WriterTInstances9 extends WriterTInstances10 } } -private[data] sealed abstract class WriterTInstances10 { +private[data] sealed abstract class WriterTInstances11 { implicit def catsDataCoflatMapForWriterT[F[_], L](implicit F: Functor[F]): CoflatMap[WriterT[F, L, ?]] = new WriterTCoflatMap[F, L] { implicit val F0: Functor[F] = F @@ -429,6 +438,13 @@ private[data] sealed trait WriterTFoldable[F[_], L] extends Foldable[WriterT[F, def foldRight[A, B](fa: WriterT[F, L, A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = fa.foldRight(lb)(f) } +private[data] sealed trait WriterTTraverse[F[_], L] extends Traverse[WriterT[F, L, ?]] with WriterTFoldable[F, L] { + + implicit def F0: Traverse[F] + + def traverse[G[_]: Applicative, A, B](fa: WriterT[F, L, A])(f: A => G[B]): G[WriterT[F, L, B]] = fa.traverse(f) +} + private[data] trait WriterTFunctions { def putT[F[_], L, V](vf: F[V])(l: L)(implicit functorF: Functor[F]): WriterT[F, L, V] = WriterT(functorF.map(vf)(v => (l, v))) From e68849d2cd92140d2f0a179c459eae7e3147bce4 Mon Sep 17 00:00:00 2001 From: Filippo Mariotti Date: Sun, 4 Mar 2018 19:45:12 +0000 Subject: [PATCH 04/16] Added traverse implementation to WriterT --- core/src/main/scala/cats/data/WriterT.scala | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index f78c2e42be..5d3aee38c6 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -70,7 +70,10 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) { def foldRight[C](lc: Eval[C])(f: (V, Eval[C]) => Eval[C])(implicit F: Foldable[F]): Eval[C] = F.foldRight(run, lc)((v, z) => f(v._2, z)) - def traverse[G[_], V1](f: V => G[V1])(implicit F: Traverse[F], G: Applicative[G]): G[WriterT[F, L, V1]] = ??? + def traverse[G[_], V1](f: V => G[V1])(implicit F: Traverse[F], G: Applicative[G]): G[WriterT[F, L, V1]] = + G.map( + F.traverse(run)(lv => G.product(G.pure(lv._1), f(lv._2))) + )(WriterT.apply) } object WriterT extends WriterTInstances with WriterTFunctions { From 6729608a7a2536b2c5b4151f5b289063cba590fd Mon Sep 17 00:00:00 2001 From: Filippo Mariotti Date: Sun, 4 Mar 2018 21:19:30 +0000 Subject: [PATCH 05/16] Added test for WriterT Traverse --- tests/src/test/scala/cats/tests/WriterTSuite.scala | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/src/test/scala/cats/tests/WriterTSuite.scala b/tests/src/test/scala/cats/tests/WriterTSuite.scala index 7836be91ac..c159d4c7fa 100644 --- a/tests/src/test/scala/cats/tests/WriterTSuite.scala +++ b/tests/src/test/scala/cats/tests/WriterTSuite.scala @@ -373,12 +373,21 @@ class WriterTSuite extends CatsSuite { { // F has a Foldable and L has a Monoid implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monoid[Int] - Foldable[WriterT[Const[String, ?], Int, ?]] + Foldable[WriterT[Const[String, ?], ListWrapper[Int], ?]] checkAll("WriterT[Const[String, ?], ListWrapper[Int], ?]", FoldableTests[WriterT[Const[String, ?], ListWrapper[Int], ?]].foldable[Int, Int]) checkAll("Foldable[WriterT[Const[String, ?], ListWrapper[Int], ?]]", SerializableTests.serializable(Foldable[WriterT[Const[String, ?], ListWrapper[Int], ?]])) } + { + // F has a Traverse and L has a Monoid + implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monoid[Int] + Traverse[WriterT[Const[String, ?], ListWrapper[Int], ?]] + + checkAll("WriterT[Const[String, ?], ListWrapper[Int], ?]", TraverseTests[WriterT[Const[String, ?], ListWrapper[Int], ?]].traverse[Int, Int, Int, Int, Option, Option]) + checkAll("Traverse[WriterT[Const[String, ?], ListWrapper[Int], ?]]", SerializableTests.serializable(Traverse[WriterT[Const[String, ?], ListWrapper[Int], ?]])) + } + checkAll("WriterT[Option, Int, ?]", CommutativeMonadTests[WriterT[Option, Int, ?]].commutativeMonad[Int, Int, Int]) checkAll("CommutativeMonad[WriterT[Option, Int, ?]]",SerializableTests.serializable(CommutativeMonad[WriterT[Option, Int, ?]])) } From 2a7f5f2b2999e453cc684cdce9337938f4b677a2 Mon Sep 17 00:00:00 2001 From: Filippo Mariotti Date: Mon, 5 Mar 2018 00:31:20 +0000 Subject: [PATCH 06/16] Refactored names --- core/src/main/scala/cats/data/WriterT.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index 5d3aee38c6..ff7b09016d 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -65,10 +65,10 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) { def show(implicit F: Show[F[(L, V)]]): String = F.show(run) def foldLeft[C](c: C)(f: (C, V) => C)(implicit F: Foldable[F]): C = - F.foldLeft(run, c)((z, v) => f(z, v._2)) + F.foldLeft(run, c)((z, lv) => f(z, lv._2)) def foldRight[C](lc: Eval[C])(f: (V, Eval[C]) => Eval[C])(implicit F: Foldable[F]): Eval[C] = - F.foldRight(run, lc)((v, z) => f(v._2, z)) + F.foldRight(run, lc)((lv, z) => f(lv._2, z)) def traverse[G[_], V1](f: V => G[V1])(implicit F: Traverse[F], G: Applicative[G]): G[WriterT[F, L, V1]] = G.map( From 454cc8f6af0322716971bb81f0f24ec9e1258762 Mon Sep 17 00:00:00 2001 From: Filippo Mariotti Date: Mon, 5 Mar 2018 16:18:51 +0000 Subject: [PATCH 07/16] Changed priority of Traverse instance --- core/src/main/scala/cats/data/WriterT.scala | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index ff7b09016d..74b842b6eb 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -106,11 +106,6 @@ private[data] sealed abstract class WriterTInstances extends WriterTInstances0 { implicit val F0: Monad[F] = F implicit val L0: Monoid[L] = L } - - implicit def catsDataFoldableForWriterT[F[_], L, V](implicit F: Foldable[F]): Foldable[WriterT[F, L, ?]] = - new WriterTFoldable[F, L]{ - val F0: Foldable[F] = F - } } private[data] sealed abstract class WriterTInstances0 extends WriterTInstances1 { @@ -157,6 +152,11 @@ private[data] sealed abstract class WriterTInstances1 extends WriterTInstances2 implicit def catsDataMonoidForWriterTId[L:Monoid, V:Monoid]: Monoid[WriterT[Id, L, V]] = catsDataMonoidForWriterT[Id, L, V] + + implicit def catsDataFoldableForWriterT[F[_], L, V](implicit F: Foldable[F]): Foldable[WriterT[F, L, ?]] = + new WriterTFoldable[F, L]{ + val F0: Foldable[F] = F + } } private[data] sealed abstract class WriterTInstances2 extends WriterTInstances3 { From 4cf8304259427f5863e6fe970bfc72ed26c8e403 Mon Sep 17 00:00:00 2001 From: Filippo Mariotti Date: Wed, 7 Mar 2018 09:40:54 +0000 Subject: [PATCH 08/16] Added comonad instance for WrtiterT and Const. Added tests --- core/src/main/scala/cats/data/Const.scala | 12 +++++++++++- core/src/main/scala/cats/data/WriterT.scala | 19 ++++++++++++++++--- .../test/scala/cats/tests/WriterTSuite.scala | 9 +++++++++ 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/core/src/main/scala/cats/data/Const.scala b/core/src/main/scala/cats/data/Const.scala index 631a9327cd..7ed16a0114 100644 --- a/core/src/main/scala/cats/data/Const.scala +++ b/core/src/main/scala/cats/data/Const.scala @@ -134,7 +134,7 @@ private[data] sealed abstract class ConstInstances0 extends ConstInstances1 { } } -private[data] sealed abstract class ConstInstances1 { +private[data] sealed abstract class ConstInstances1 extends ConstInstances2 { implicit def catsDataEqForConst[A: Eq, B]: Eq[Const[A, B]] = new Eq[Const[A, B]] { def eqv(x: Const[A, B], y: Const[A, B]): Boolean = @@ -152,3 +152,13 @@ private[data] sealed abstract class ConstInstances1 { fa.retag[B] } } + +private[data] sealed abstract class ConstInstances2 { + + implicit def catsDataComonadForConst[C]: Comonad[Const[C, ?]] = + new Comonad[Const[C, ?]] { + def coflatMap[A, B](fa: Const[C,A])(f: Const[C,A] => B): Const[C,B] = ??? + def extract[A](x: Const[C,A]): A = ??? + def map[A, B](fa: Const[C,A])(f: A => B): Const[C,B] = ??? + } +} \ No newline at end of file diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index 74b842b6eb..27bf1f4484 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -253,7 +253,6 @@ private[data] sealed abstract class WriterTInstances9 extends WriterTInstances10 implicit val F0: Applicative[F] = F implicit val L0: Monoid[L] = L } - } private[data] sealed abstract class WriterTInstances10 extends WriterTInstances11 { @@ -264,7 +263,14 @@ private[data] sealed abstract class WriterTInstances10 extends WriterTInstances1 } } -private[data] sealed abstract class WriterTInstances11 { +private[data] sealed abstract class WriterTInstances11 extends WriterTInstances12 { + implicit def catsDataComonadForWriterT[F[_], L](implicit F: Comonad[F]): Comonad[WriterT[F, L, ?]] = + new WriterTComonad[F, L] { + implicit val F0: Comonad[F] = F + } +} + +private[data] sealed abstract class WriterTInstances12 { implicit def catsDataCoflatMapForWriterT[F[_], L](implicit F: Functor[F]): CoflatMap[WriterT[F, L, ?]] = new WriterTCoflatMap[F, L] { implicit val F0: Functor[F] = F @@ -433,6 +439,13 @@ private[data] sealed trait WriterTCoflatMap[F[_], L] extends CoflatMap[WriterT[F def coflatMap[A, B](fa: WriterT[F, L, A])(f: WriterT[F, L, A] => B): WriterT[F, L, B] = fa.map(_ => f(fa)) } +private[data] sealed trait WriterTComonad[F[_], L] extends Comonad[WriterT[F, L, ?]] with WriterTCoflatMap[F, L] { + + override implicit def F0: Comonad[F] + + def extract[A](fa: WriterT[F, L, A]): A = F0.extract(fa.value) +} + private[data] sealed trait WriterTFoldable[F[_], L] extends Foldable[WriterT[F, L, ?]] { implicit def F0: Foldable[F] @@ -443,7 +456,7 @@ private[data] sealed trait WriterTFoldable[F[_], L] extends Foldable[WriterT[F, private[data] sealed trait WriterTTraverse[F[_], L] extends Traverse[WriterT[F, L, ?]] with WriterTFoldable[F, L] { - implicit def F0: Traverse[F] + override implicit def F0: Traverse[F] def traverse[G[_]: Applicative, A, B](fa: WriterT[F, L, A])(f: A => G[B]): G[WriterT[F, L, B]] = fa.traverse(f) } diff --git a/tests/src/test/scala/cats/tests/WriterTSuite.scala b/tests/src/test/scala/cats/tests/WriterTSuite.scala index c159d4c7fa..32fe15b5b8 100644 --- a/tests/src/test/scala/cats/tests/WriterTSuite.scala +++ b/tests/src/test/scala/cats/tests/WriterTSuite.scala @@ -388,6 +388,15 @@ class WriterTSuite extends CatsSuite { checkAll("Traverse[WriterT[Const[String, ?], ListWrapper[Int], ?]]", SerializableTests.serializable(Traverse[WriterT[Const[String, ?], ListWrapper[Int], ?]])) } + { + // F has a Comonad and L has a Monoid + implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monoid[Int] + Comonad[WriterT[Const[String, ?], ListWrapper[Int], ?]] + + checkAll("WriterT[Const[String, ?], ListWrapper[Int], ?]", ComonadTests[WriterT[Const[String, ?], ListWrapper[Int], ?]].comonad[Int, Int, Int]) + checkAll("Comonad[WriterT[Const[String, ?], ListWrapper[Int], ?]]", SerializableTests.serializable(Comonad[WriterT[Const[String, ?], ListWrapper[Int], ?]])) + } + checkAll("WriterT[Option, Int, ?]", CommutativeMonadTests[WriterT[Option, Int, ?]].commutativeMonad[Int, Int, Int]) checkAll("CommutativeMonad[WriterT[Option, Int, ?]]",SerializableTests.serializable(CommutativeMonad[WriterT[Option, Int, ?]])) } From 0c2c0025209ec3a0d7f42347562e245677551e6f Mon Sep 17 00:00:00 2001 From: Filippo Mariotti Date: Wed, 7 Mar 2018 10:47:35 +0000 Subject: [PATCH 09/16] Completed Comonad tests using tuple instead of Const --- core/src/main/scala/cats/data/Const.scala | 12 +----------- tests/src/test/scala/cats/tests/WriterTSuite.scala | 6 +++--- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/core/src/main/scala/cats/data/Const.scala b/core/src/main/scala/cats/data/Const.scala index 7ed16a0114..631a9327cd 100644 --- a/core/src/main/scala/cats/data/Const.scala +++ b/core/src/main/scala/cats/data/Const.scala @@ -134,7 +134,7 @@ private[data] sealed abstract class ConstInstances0 extends ConstInstances1 { } } -private[data] sealed abstract class ConstInstances1 extends ConstInstances2 { +private[data] sealed abstract class ConstInstances1 { implicit def catsDataEqForConst[A: Eq, B]: Eq[Const[A, B]] = new Eq[Const[A, B]] { def eqv(x: Const[A, B], y: Const[A, B]): Boolean = @@ -152,13 +152,3 @@ private[data] sealed abstract class ConstInstances1 extends ConstInstances2 { fa.retag[B] } } - -private[data] sealed abstract class ConstInstances2 { - - implicit def catsDataComonadForConst[C]: Comonad[Const[C, ?]] = - new Comonad[Const[C, ?]] { - def coflatMap[A, B](fa: Const[C,A])(f: Const[C,A] => B): Const[C,B] = ??? - def extract[A](x: Const[C,A]): A = ??? - def map[A, B](fa: Const[C,A])(f: A => B): Const[C,B] = ??? - } -} \ No newline at end of file diff --git a/tests/src/test/scala/cats/tests/WriterTSuite.scala b/tests/src/test/scala/cats/tests/WriterTSuite.scala index 32fe15b5b8..81d259303d 100644 --- a/tests/src/test/scala/cats/tests/WriterTSuite.scala +++ b/tests/src/test/scala/cats/tests/WriterTSuite.scala @@ -391,10 +391,10 @@ class WriterTSuite extends CatsSuite { { // F has a Comonad and L has a Monoid implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monoid[Int] - Comonad[WriterT[Const[String, ?], ListWrapper[Int], ?]] + Comonad[WriterT[(String, ?), ListWrapper[Int], ?]] - checkAll("WriterT[Const[String, ?], ListWrapper[Int], ?]", ComonadTests[WriterT[Const[String, ?], ListWrapper[Int], ?]].comonad[Int, Int, Int]) - checkAll("Comonad[WriterT[Const[String, ?], ListWrapper[Int], ?]]", SerializableTests.serializable(Comonad[WriterT[Const[String, ?], ListWrapper[Int], ?]])) + checkAll("WriterT[(String, ?), ListWrapper[Int], ?]", ComonadTests[WriterT[(String, ?), ListWrapper[Int], ?]].comonad[Int, Int, Int]) + checkAll("Comonad[WriterT[(String, ?), ListWrapper[Int], ?]]", SerializableTests.serializable(Comonad[WriterT[(String, ?), ListWrapper[Int], ?]])) } checkAll("WriterT[Option, Int, ?]", CommutativeMonadTests[WriterT[Option, Int, ?]].commutativeMonad[Int, Int, Int]) From e63a7e37b1e95684715f42aba6ac5be8a48e6aba Mon Sep 17 00:00:00 2001 From: Filippo Mariotti Date: Wed, 7 Mar 2018 15:10:53 +0000 Subject: [PATCH 10/16] Refactored extract derivation to avoid implicit search --- core/src/main/scala/cats/data/WriterT.scala | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index 27bf1f4484..73c50b22e3 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -439,13 +439,6 @@ private[data] sealed trait WriterTCoflatMap[F[_], L] extends CoflatMap[WriterT[F def coflatMap[A, B](fa: WriterT[F, L, A])(f: WriterT[F, L, A] => B): WriterT[F, L, B] = fa.map(_ => f(fa)) } -private[data] sealed trait WriterTComonad[F[_], L] extends Comonad[WriterT[F, L, ?]] with WriterTCoflatMap[F, L] { - - override implicit def F0: Comonad[F] - - def extract[A](fa: WriterT[F, L, A]): A = F0.extract(fa.value) -} - private[data] sealed trait WriterTFoldable[F[_], L] extends Foldable[WriterT[F, L, ?]] { implicit def F0: Foldable[F] @@ -461,6 +454,13 @@ private[data] sealed trait WriterTTraverse[F[_], L] extends Traverse[WriterT[F, def traverse[G[_]: Applicative, A, B](fa: WriterT[F, L, A])(f: A => G[B]): G[WriterT[F, L, B]] = fa.traverse(f) } +private[data] sealed trait WriterTComonad[F[_], L] extends Comonad[WriterT[F, L, ?]] with WriterTCoflatMap[F, L] { + + override implicit def F0: Comonad[F] + + def extract[A](fa: WriterT[F, L, A]): A = F0.extract(F0.map(fa.run)(_._2)) +} + private[data] trait WriterTFunctions { def putT[F[_], L, V](vf: F[V])(l: L)(implicit functorF: Functor[F]): WriterT[F, L, V] = WriterT(functorF.map(vf)(v => (l, v))) From fba0f7a38c59ae5c7ac8b6c43fe7765541d97f5d Mon Sep 17 00:00:00 2001 From: Filippo Mariotti Date: Fri, 9 Mar 2018 16:20:11 +0000 Subject: [PATCH 11/16] Added instances and reolution tests for Id. Removed unneeded type parameters. --- core/src/main/scala/cats/data/WriterT.scala | 14 ++++++++++++-- .../src/test/scala/cats/tests/WriterTSuite.scala | 15 +++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index 73c50b22e3..da2c5bab76 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -106,13 +106,20 @@ private[data] sealed abstract class WriterTInstances extends WriterTInstances0 { implicit val F0: Monad[F] = F implicit val L0: Monoid[L] = L } + + implicit def catsDataTraverseForWriterTId[L](implicit F: Traverse[Id]): Traverse[WriterT[Id, L, ?]] = + catsDataTraverseForWriterT[Id, L] } private[data] sealed abstract class WriterTInstances0 extends WriterTInstances1 { - implicit def catsDataTraverseForWriterT[F[_], L, V](implicit F: Traverse[F]): Traverse[WriterT[F, L, ?]] = + + implicit def catsDataTraverseForWriterT[F[_], L](implicit F: Traverse[F]): Traverse[WriterT[F, L, ?]] = new WriterTTraverse[F, L] { val F0: Traverse[F] = F } + + implicit def catsDataFoldableForWriterTId[L](implicit F: Foldable[Id]): Foldable[WriterT[Id, L, ?]] = + catsDataFoldableForWriterT[Id, L] } private[data] sealed abstract class WriterTInstances1 extends WriterTInstances2 { @@ -153,7 +160,7 @@ private[data] sealed abstract class WriterTInstances1 extends WriterTInstances2 implicit def catsDataMonoidForWriterTId[L:Monoid, V:Monoid]: Monoid[WriterT[Id, L, V]] = catsDataMonoidForWriterT[Id, L, V] - implicit def catsDataFoldableForWriterT[F[_], L, V](implicit F: Foldable[F]): Foldable[WriterT[F, L, ?]] = + implicit def catsDataFoldableForWriterT[F[_], L](implicit F: Foldable[F]): Foldable[WriterT[F, L, ?]] = new WriterTFoldable[F, L]{ val F0: Foldable[F] = F } @@ -168,6 +175,9 @@ private[data] sealed abstract class WriterTInstances2 extends WriterTInstances3 implicit def catsDataSemigroupForWriterTId[L:Semigroup, V:Semigroup]: Semigroup[WriterT[Id, L, V]] = catsDataSemigroupForWriterT[Id, L, V] + + implicit def catsDataComonadForWriterTId[L](implicit F: Comonad[Id]): Comonad[WriterT[Id, L, ?]] = + catsDataComonadForWriterT[Id, L] } private[data] sealed abstract class WriterTInstances3 extends WriterTInstances4 { diff --git a/tests/src/test/scala/cats/tests/WriterTSuite.scala b/tests/src/test/scala/cats/tests/WriterTSuite.scala index 81d259303d..cb3b5acf48 100644 --- a/tests/src/test/scala/cats/tests/WriterTSuite.scala +++ b/tests/src/test/scala/cats/tests/WriterTSuite.scala @@ -373,28 +373,43 @@ class WriterTSuite extends CatsSuite { { // F has a Foldable and L has a Monoid implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monoid[Int] + Foldable[Const[String, ?]] Foldable[WriterT[Const[String, ?], ListWrapper[Int], ?]] checkAll("WriterT[Const[String, ?], ListWrapper[Int], ?]", FoldableTests[WriterT[Const[String, ?], ListWrapper[Int], ?]].foldable[Int, Int]) checkAll("Foldable[WriterT[Const[String, ?], ListWrapper[Int], ?]]", SerializableTests.serializable(Foldable[WriterT[Const[String, ?], ListWrapper[Int], ?]])) + + Foldable[Id] + Foldable[WriterT[Id, ListWrapper[Int], ?]] + Foldable[Writer[ListWrapper[Int], ?]] } { // F has a Traverse and L has a Monoid implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monoid[Int] + Traverse[Const[String, ?]] Traverse[WriterT[Const[String, ?], ListWrapper[Int], ?]] checkAll("WriterT[Const[String, ?], ListWrapper[Int], ?]", TraverseTests[WriterT[Const[String, ?], ListWrapper[Int], ?]].traverse[Int, Int, Int, Int, Option, Option]) checkAll("Traverse[WriterT[Const[String, ?], ListWrapper[Int], ?]]", SerializableTests.serializable(Traverse[WriterT[Const[String, ?], ListWrapper[Int], ?]])) + + Traverse[Id] + Traverse[WriterT[Id, ListWrapper[Int], ?]] + Traverse[Writer[ListWrapper[Int], ?]] } { // F has a Comonad and L has a Monoid implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monoid[Int] + Comonad[(String, ?)] Comonad[WriterT[(String, ?), ListWrapper[Int], ?]] checkAll("WriterT[(String, ?), ListWrapper[Int], ?]", ComonadTests[WriterT[(String, ?), ListWrapper[Int], ?]].comonad[Int, Int, Int]) checkAll("Comonad[WriterT[(String, ?), ListWrapper[Int], ?]]", SerializableTests.serializable(Comonad[WriterT[(String, ?), ListWrapper[Int], ?]])) + + Comonad[Id] + Comonad[WriterT[Id, ListWrapper[Int], ?]] + Comonad[Writer[ListWrapper[Int], ?]] } checkAll("WriterT[Option, Int, ?]", CommutativeMonadTests[WriterT[Option, Int, ?]].commutativeMonad[Int, Int, Int]) From 2e4b2b5a9e64292ceccf75650e1e7a864563805a Mon Sep 17 00:00:00 2001 From: Filippo Mariotti Date: Fri, 9 Mar 2018 17:15:52 +0000 Subject: [PATCH 12/16] Minor refactoring --- core/src/main/scala/cats/data/WriterT.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index da2c5bab76..9495d6ad12 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -108,7 +108,7 @@ private[data] sealed abstract class WriterTInstances extends WriterTInstances0 { } implicit def catsDataTraverseForWriterTId[L](implicit F: Traverse[Id]): Traverse[WriterT[Id, L, ?]] = - catsDataTraverseForWriterT[Id, L] + catsDataTraverseForWriterT[Id, L](F) } private[data] sealed abstract class WriterTInstances0 extends WriterTInstances1 { @@ -119,7 +119,7 @@ private[data] sealed abstract class WriterTInstances0 extends WriterTInstances1 } implicit def catsDataFoldableForWriterTId[L](implicit F: Foldable[Id]): Foldable[WriterT[Id, L, ?]] = - catsDataFoldableForWriterT[Id, L] + catsDataFoldableForWriterT[Id, L](F) } private[data] sealed abstract class WriterTInstances1 extends WriterTInstances2 { @@ -177,7 +177,7 @@ private[data] sealed abstract class WriterTInstances2 extends WriterTInstances3 catsDataSemigroupForWriterT[Id, L, V] implicit def catsDataComonadForWriterTId[L](implicit F: Comonad[Id]): Comonad[WriterT[Id, L, ?]] = - catsDataComonadForWriterT[Id, L] + catsDataComonadForWriterT[Id, L](F) } private[data] sealed abstract class WriterTInstances3 extends WriterTInstances4 { From fd077c3da40177194e1e6887a44622a54a504454 Mon Sep 17 00:00:00 2001 From: Filippo Mariotti Date: Fri, 9 Mar 2018 21:28:00 +0000 Subject: [PATCH 13/16] Attempt to increase coverage --- tests/src/test/scala/cats/tests/WriterTSuite.scala | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/src/test/scala/cats/tests/WriterTSuite.scala b/tests/src/test/scala/cats/tests/WriterTSuite.scala index cb3b5acf48..2d0c794000 100644 --- a/tests/src/test/scala/cats/tests/WriterTSuite.scala +++ b/tests/src/test/scala/cats/tests/WriterTSuite.scala @@ -382,6 +382,9 @@ class WriterTSuite extends CatsSuite { Foldable[Id] Foldable[WriterT[Id, ListWrapper[Int], ?]] Foldable[Writer[ListWrapper[Int], ?]] + + checkAll("WriterT[Id, ListWrapper[Int], ?]", FoldableTests[WriterT[Id, ListWrapper[Int], ?]].foldable[Int, Int]) + checkAll("Foldable[WriterT[Id, ListWrapper[Int], ?]]", SerializableTests.serializable(Foldable[WriterT[Id, ListWrapper[Int], ?]])) } { @@ -396,6 +399,9 @@ class WriterTSuite extends CatsSuite { Traverse[Id] Traverse[WriterT[Id, ListWrapper[Int], ?]] Traverse[Writer[ListWrapper[Int], ?]] + + checkAll("WriterT[Id, ListWrapper[Int], ?]", TraverseTests[WriterT[Id, ListWrapper[Int], ?]].traverse[Int, Int, Int, Int, Option, Option]) + checkAll("Traverse[WriterT[Id, ListWrapper[Int], ?]]", SerializableTests.serializable(Traverse[WriterT[Id, ListWrapper[Int], ?]])) } { @@ -410,6 +416,9 @@ class WriterTSuite extends CatsSuite { Comonad[Id] Comonad[WriterT[Id, ListWrapper[Int], ?]] Comonad[Writer[ListWrapper[Int], ?]] + + checkAll("WriterT[Id, ListWrapper[Int], ?]", ComonadTests[WriterT[Id, ListWrapper[Int], ?]].comonad[Int, Int, Int]) + checkAll("Comonad[WriterT[Id, ListWrapper[Int], ?]]", SerializableTests.serializable(Comonad[WriterT[Id, ListWrapper[Int], ?]])) } checkAll("WriterT[Option, Int, ?]", CommutativeMonadTests[WriterT[Option, Int, ?]].commutativeMonad[Int, Int, Int]) From a40e9f794e58d4822f56566fa373df97a7408703 Mon Sep 17 00:00:00 2001 From: Filippo Mariotti Date: Fri, 9 Mar 2018 22:32:06 +0000 Subject: [PATCH 14/16] Removed unneeded serialization test --- tests/src/test/scala/cats/tests/WriterTSuite.scala | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/src/test/scala/cats/tests/WriterTSuite.scala b/tests/src/test/scala/cats/tests/WriterTSuite.scala index 2d0c794000..19b98868ab 100644 --- a/tests/src/test/scala/cats/tests/WriterTSuite.scala +++ b/tests/src/test/scala/cats/tests/WriterTSuite.scala @@ -384,7 +384,6 @@ class WriterTSuite extends CatsSuite { Foldable[Writer[ListWrapper[Int], ?]] checkAll("WriterT[Id, ListWrapper[Int], ?]", FoldableTests[WriterT[Id, ListWrapper[Int], ?]].foldable[Int, Int]) - checkAll("Foldable[WriterT[Id, ListWrapper[Int], ?]]", SerializableTests.serializable(Foldable[WriterT[Id, ListWrapper[Int], ?]])) } { @@ -401,7 +400,6 @@ class WriterTSuite extends CatsSuite { Traverse[Writer[ListWrapper[Int], ?]] checkAll("WriterT[Id, ListWrapper[Int], ?]", TraverseTests[WriterT[Id, ListWrapper[Int], ?]].traverse[Int, Int, Int, Int, Option, Option]) - checkAll("Traverse[WriterT[Id, ListWrapper[Int], ?]]", SerializableTests.serializable(Traverse[WriterT[Id, ListWrapper[Int], ?]])) } { @@ -418,7 +416,6 @@ class WriterTSuite extends CatsSuite { Comonad[Writer[ListWrapper[Int], ?]] checkAll("WriterT[Id, ListWrapper[Int], ?]", ComonadTests[WriterT[Id, ListWrapper[Int], ?]].comonad[Int, Int, Int]) - checkAll("Comonad[WriterT[Id, ListWrapper[Int], ?]]", SerializableTests.serializable(Comonad[WriterT[Id, ListWrapper[Int], ?]])) } checkAll("WriterT[Option, Int, ?]", CommutativeMonadTests[WriterT[Option, Int, ?]].commutativeMonad[Int, Int, Int]) From b3ab66428ae2c45ede7c0c0c51872582042fd8b0 Mon Sep 17 00:00:00 2001 From: Filippo Mariotti Date: Mon, 12 Mar 2018 11:32:30 +0000 Subject: [PATCH 15/16] Refactored traverse derivation --- core/src/main/scala/cats/data/WriterT.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index 9495d6ad12..1b32363e8d 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -72,7 +72,7 @@ final case class WriterT[F[_], L, V](run: F[(L, V)]) { def traverse[G[_], V1](f: V => G[V1])(implicit F: Traverse[F], G: Applicative[G]): G[WriterT[F, L, V1]] = G.map( - F.traverse(run)(lv => G.product(G.pure(lv._1), f(lv._2))) + F.traverse(run)(lv => G.tupleLeft(f(lv._2), lv._1)) )(WriterT.apply) } @@ -457,10 +457,11 @@ private[data] sealed trait WriterTFoldable[F[_], L] extends Foldable[WriterT[F, def foldRight[A, B](fa: WriterT[F, L, A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = fa.foldRight(lb)(f) } -private[data] sealed trait WriterTTraverse[F[_], L] extends Traverse[WriterT[F, L, ?]] with WriterTFoldable[F, L] { +private[data] sealed trait WriterTTraverse[F[_], L] extends Traverse[WriterT[F, L, ?]] with WriterTFoldable[F, L] with WriterTFunctor[F, L] { override implicit def F0: Traverse[F] + override def map[A, B](fa: WriterT[F, L, A])(f: A => B): WriterT[F, L, B] = super[WriterTFunctor].map(fa)(f) def traverse[G[_]: Applicative, A, B](fa: WriterT[F, L, A])(f: A => G[B]): G[WriterT[F, L, B]] = fa.traverse(f) } From 152ee7a933ed3a31c7a9103245f8eef8e995bb7a Mon Sep 17 00:00:00 2001 From: Filippo Mariotti Date: Mon, 12 Mar 2018 15:14:47 +0000 Subject: [PATCH 16/16] Fixed improper inheritance of WriterTFunctor --- core/src/main/scala/cats/data/WriterT.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index 1b32363e8d..1f09eb8723 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -290,7 +290,7 @@ private[data] sealed abstract class WriterTInstances12 { private[data] sealed trait WriterTFunctor[F[_], L] extends Functor[WriterT[F, L, ?]] { implicit def F0: Functor[F] - def map[A, B](fa: WriterT[F, L, A])(f: A => B): WriterT[F, L, B] = + override def map[A, B](fa: WriterT[F, L, A])(f: A => B): WriterT[F, L, B] = fa.map(f) } @@ -461,7 +461,6 @@ private[data] sealed trait WriterTTraverse[F[_], L] extends Traverse[WriterT[F, override implicit def F0: Traverse[F] - override def map[A, B](fa: WriterT[F, L, A])(f: A => B): WriterT[F, L, B] = super[WriterTFunctor].map(fa)(f) def traverse[G[_]: Applicative, A, B](fa: WriterT[F, L, A])(f: A => G[B]): G[WriterT[F, L, B]] = fa.traverse(f) }