From 355db32968e5fd0b01673d8e092fb437cf7cd98b Mon Sep 17 00:00:00 2001 From: Cody Allen Date: Mon, 23 Nov 2015 08:32:29 -0500 Subject: [PATCH] Add more WriterT instances * SemigroupK * MonoidK * Alternative * MonadFilter * MonadCombine --- core/src/main/scala/cats/data/WriterT.scala | 73 +++++++++++++++++-- .../test/scala/cats/tests/ListWrapper.scala | 6 ++ .../test/scala/cats/tests/WriterTTests.scala | 70 +++++++++++++++++- 3 files changed, 139 insertions(+), 10 deletions(-) diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index 69dbc5f079..304f2796c7 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -65,9 +65,9 @@ private[data] sealed abstract class WriterTInstances extends WriterTInstances0 { } private[data] sealed abstract class WriterTInstances0 extends WriterTInstances1 { - implicit def writerTMonad[F[_], L](implicit F: Monad[F], L: Monoid[L]): Monad[WriterT[F, L, ?]] = - new WriterTMonad[F, L] { - implicit val F0: Monad[F] = F + implicit def writerTMonadCombine[F[_], L](implicit F: MonadCombine[F], L: Monoid[L]): MonadCombine[WriterT[F, L, ?]] = + new WriterTMonadCombine[F, L] { + implicit val F0: MonadCombine[F] = F implicit val L0: Monoid[L] = L } @@ -82,21 +82,55 @@ private[data] sealed abstract class WriterTInstances0 extends WriterTInstances1 } private[data] sealed abstract class WriterTInstances1 extends WriterTInstances2 { + implicit def writerTMonadFilter[F[_], L](implicit F: MonadFilter[F], L: Monoid[L]): MonadFilter[WriterT[F, L, ?]] = + new WriterTMonadFilter[F, L] { + implicit val F0: MonadFilter[F] = F + implicit val L0: Monoid[L] = L + } +} +private[data] sealed abstract class WriterTInstances2 extends WriterTInstances3 { + implicit def writerTMonad[F[_], L](implicit F: Monad[F], L: Monoid[L]): Monad[WriterT[F, L, ?]] = + new WriterTMonad[F, L] { + implicit val F0: Monad[F] = F + implicit val L0: Monoid[L] = L + } +} + +private[data] sealed abstract class WriterTInstances3 extends WriterTInstances4 { + implicit def writerTAlternative[F[_], L](implicit F: Alternative[F], L: Monoid[L]): Alternative[WriterT[F, L, ?]] = + new WriterTAlternative[F, L] { + implicit val F0: Alternative[F] = F + implicit val L0: Monoid[L] = L + } +} + +private[data] sealed abstract class WriterTInstances4 extends WriterTInstances5 { implicit def writerTApplicative[F[_], L](implicit F: Applicative[F], L: Monoid[L]): Applicative[WriterT[F, L, ?]] = new WriterTApplicative[F, L] { implicit val F0: Applicative[F] = F implicit val L0: Monoid[L] = L } + + implicit def writerTMonoidK[F[_], L](implicit F: MonoidK[F]): MonoidK[WriterT[F, L, ?]] = + new WriterTMonoidK[F, L] { + implicit val F0: MonoidK[F] = F + } } -private[data] sealed abstract class WriterTInstances2 extends WriterTInstances3 { + +private[data] sealed abstract class WriterTInstances5 extends WriterTInstances6 { implicit def writerTFlatMap[F[_], L](implicit F: FlatMap[F], L: Semigroup[L]): FlatMap[WriterT[F, L, ?]] = new WriterTFlatMap[F, L] { implicit val F0: FlatMap[F] = F implicit val L0: Semigroup[L] = L } + + implicit def writerTSemigroupK[F[_], L](implicit F: SemigroupK[F]): SemigroupK[WriterT[F, L, ?]] = + new WriterTSemigroupK[F, L] { + implicit val F0: SemigroupK[F] = F + } } -private[data] sealed abstract class WriterTInstances3 extends WriterTInstances4 { +private[data] sealed abstract class WriterTInstances6 extends WriterTInstances7 { implicit def writerTApply[F[_], L](implicit F: Apply[F], L: Semigroup[L]): Apply[WriterT[F, L, ?]] = new WriterTApply[F, L] { implicit val F0: Apply[F] = F @@ -104,7 +138,7 @@ private[data] sealed abstract class WriterTInstances3 extends WriterTInstances4 } } -private[data] sealed abstract class WriterTInstances4 { +private[data] sealed abstract class WriterTInstances7 { implicit def writerTFunctor[F[_], L](implicit F: Functor[F]): Functor[WriterT[F, L, ?]] = new WriterTFunctor[F, L] { implicit val F0: Functor[F] = F } @@ -149,6 +183,33 @@ private[data] sealed trait WriterTMonad[F[_], L] extends WriterTApplicative[F, L fa.flatMap(f) } +private[data] sealed trait WriterTSemigroupK[F[_], L] extends SemigroupK[WriterT[F, L, ?]] { + implicit def F0: SemigroupK[F] + + def combine[A](x: WriterT[F, L, A], y: WriterT[F, L, A]): WriterT[F, L, A] = + WriterT(F0.combine(x.run, y.run)) +} + +private[data] sealed trait WriterTMonoidK[F[_], L] extends MonoidK[WriterT[F, L, ?]] with WriterTSemigroupK[F, L] { + override implicit def F0: MonoidK[F] + + def empty[A]: WriterT[F, L, A] = WriterT(F0.empty) +} + +private[data] sealed trait WriterTAlternative[F[_], L] extends Alternative[WriterT[F, L, ?]] with WriterTMonoidK[F, L] with WriterTApplicative[F, L] { + override implicit def F0: Alternative[F] +} + +private[data] sealed trait WriterTMonadFilter[F[_], L] extends MonadFilter[WriterT[F, L, ?]] with WriterTMonad[F, L] { + override implicit def F0: MonadFilter[F] + + def empty[A]: WriterT[F, L, A] = WriterT(F0.empty) +} + +private[data] sealed trait WriterTMonadCombine[F[_], L] extends MonadCombine[WriterT[F, L, ?]] with WriterTMonad[F, L] with WriterTAlternative[F, L] { + override implicit def F0: MonadCombine[F] +} + 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))) diff --git a/tests/src/test/scala/cats/tests/ListWrapper.scala b/tests/src/test/scala/cats/tests/ListWrapper.scala index 35f8177570..1940880eba 100644 --- a/tests/src/test/scala/cats/tests/ListWrapper.scala +++ b/tests/src/test/scala/cats/tests/ListWrapper.scala @@ -84,6 +84,12 @@ object ListWrapper { } } + def monoidK: MonoidK[ListWrapper] = monadCombine + + def monadFilter: MonadFilter[ListWrapper] = monadCombine + + def alternative: Alternative[ListWrapper] = monadCombine + def monoid[A]: Monoid[ListWrapper[A]] = monadCombine.algebra[A] implicit def listWrapperArbitrary[A: Arbitrary]: Arbitrary[ListWrapper[A]] = diff --git a/tests/src/test/scala/cats/tests/WriterTTests.scala b/tests/src/test/scala/cats/tests/WriterTTests.scala index 9bc21198f4..b3fb61e216 100644 --- a/tests/src/test/scala/cats/tests/WriterTTests.scala +++ b/tests/src/test/scala/cats/tests/WriterTTests.scala @@ -44,6 +44,24 @@ class WriterTTests extends CatsSuite { } } + { + // F has a SemigroupK + implicit val F: SemigroupK[ListWrapper] = ListWrapper.semigroupK + + checkAll("WriterT[ListWrapper, ListWrapper[Int], ?]", SemigroupKTests[WriterT[ListWrapper, ListWrapper[Int], ?]].semigroupK[Int]) + checkAll("SemigroupK[WriterT[ListWrapper, ListWrapper[Int], ?]]", SerializableTests.serializable(SemigroupK[WriterT[ListWrapper, ListWrapper[Int], ?]])) + } + + { + // F has a MonoidK + implicit val F: MonoidK[ListWrapper] = ListWrapper.monoidK + + SemigroupK[WriterT[ListWrapper, ListWrapper[Int], ?]] + + checkAll("WriterT[ListWrapper, ListWrapper[Int], ?]", MonoidKTests[WriterT[ListWrapper, ListWrapper[Int], ?]].monoidK[Int]) + checkAll("MonoidK[WriterT[ListWrapper, ListWrapper[Int], ?]]", SerializableTests.serializable(MonoidK[WriterT[ListWrapper, ListWrapper[Int], ?]])) + } + { // F has a Functor and L has no Semigroup implicit val F: Functor[ListWrapper] = ListWrapper.functor @@ -69,7 +87,7 @@ class WriterTTests extends CatsSuite { { // F has an Apply and L has a Semigroup implicit val F: Apply[ListWrapper] = ListWrapper.monadCombine - implicit val L: Semigroup[ListWrapper[Int]] = ListWrapper.semigroupK.algebra[Int] + implicit val L: Semigroup[ListWrapper[Int]] = ListWrapper.semigroup[Int] Functor[WriterT[ListWrapper, ListWrapper[Int], ?]] checkAll("WriterT[ListWrapper, ListWrapper[Int], ?]", ApplyTests[WriterT[ListWrapper, ListWrapper[Int], ?]].apply[Int, Int, Int]) @@ -88,7 +106,7 @@ class WriterTTests extends CatsSuite { { // F has a FlatMap and L has a Semigroup implicit val F: FlatMap[ListWrapper] = ListWrapper.monadCombine - implicit val L: Semigroup[ListWrapper[Int]] = ListWrapper.semigroupK.algebra[Int] + implicit val L: Semigroup[ListWrapper[Int]] = ListWrapper.semigroup[Int] Functor[WriterT[ListWrapper, ListWrapper[Int], ?]] Apply[WriterT[ListWrapper, ListWrapper[Int], ?]] @@ -111,7 +129,7 @@ class WriterTTests extends CatsSuite { { // F has an Applicative and L has a Monoid implicit val F: Applicative[ListWrapper] = ListWrapper.monadCombine - implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monadCombine.algebra[Int] + implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monoid[Int] Functor[WriterT[ListWrapper, ListWrapper[Int], ?]] Apply[WriterT[ListWrapper, ListWrapper[Int], ?]] @@ -134,7 +152,7 @@ class WriterTTests extends CatsSuite { { // F has a Monad and L has a Monoid implicit val F: Monad[ListWrapper] = ListWrapper.monadCombine - implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monadCombine.algebra[Int] + implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monoid[Int] Functor[WriterT[ListWrapper, ListWrapper[Int], ?]] Apply[WriterT[ListWrapper, ListWrapper[Int], ?]] @@ -161,4 +179,48 @@ class WriterTTests extends CatsSuite { FlatMap[Logged] Monad[Logged] } + + { + // F has an Alternative and L has a Monoid + implicit val F: Alternative[ListWrapper] = ListWrapper.alternative + implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monoid[Int] + + Functor[WriterT[ListWrapper, ListWrapper[Int], ?]] + Apply[WriterT[ListWrapper, ListWrapper[Int], ?]] + Applicative[WriterT[ListWrapper, ListWrapper[Int], ?]] + checkAll("WriterT[ListWrapper, ListWrapper[Int], ?]", AlternativeTests[WriterT[ListWrapper, ListWrapper[Int], ?]].alternative[Int, Int, Int]) + checkAll("Alternative[WriterT[ListWrapper, ListWrapper[Int], ?]]", SerializableTests.serializable(Alternative[WriterT[ListWrapper, ListWrapper[Int], ?]])) + } + + { + // F has a MonadFilter and L has a Monoid + implicit val F: MonadFilter[ListWrapper] = ListWrapper.monadFilter + implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monoid[Int] + + Functor[WriterT[ListWrapper, ListWrapper[Int], ?]] + Apply[WriterT[ListWrapper, ListWrapper[Int], ?]] + Applicative[WriterT[ListWrapper, ListWrapper[Int], ?]] + FlatMap[WriterT[ListWrapper, ListWrapper[Int], ?]] + Monad[WriterT[ListWrapper, ListWrapper[Int], ?]] + checkAll("WriterT[ListWrapper, ListWrapper[Int], ?]", MonadFilterTests[WriterT[ListWrapper, ListWrapper[Int], ?]].monadFilter[Int, Int, Int]) + checkAll("MonadFilter[WriterT[ListWrapper, ListWrapper[Int], ?]]", SerializableTests.serializable(MonadFilter[WriterT[ListWrapper, ListWrapper[Int], ?]])) + } + + { + // F has a MonadCombine and L has a Monoid + implicit val F: MonadCombine[ListWrapper] = ListWrapper.monadCombine + implicit val L: Monoid[ListWrapper[Int]] = ListWrapper.monoid[Int] + + Functor[WriterT[ListWrapper, ListWrapper[Int], ?]] + Apply[WriterT[ListWrapper, ListWrapper[Int], ?]] + Applicative[WriterT[ListWrapper, ListWrapper[Int], ?]] + FlatMap[WriterT[ListWrapper, ListWrapper[Int], ?]] + Monad[WriterT[ListWrapper, ListWrapper[Int], ?]] + MonadFilter[WriterT[ListWrapper, ListWrapper[Int], ?]] + Alternative[WriterT[ListWrapper, ListWrapper[Int], ?]] + SemigroupK[WriterT[ListWrapper, ListWrapper[Int], ?]] + MonoidK[WriterT[ListWrapper, ListWrapper[Int], ?]] + checkAll("WriterT[ListWrapper, ListWrapper[Int], ?]", MonadCombineTests[WriterT[ListWrapper, ListWrapper[Int], ?]].monadCombine[Int, Int, Int]) + checkAll("MonadCombine[WriterT[ListWrapper, ListWrapper[Int], ?]]", SerializableTests.serializable(MonadCombine[WriterT[ListWrapper, ListWrapper[Int], ?]])) + } }