diff --git a/core/src/main/scala/cats/MonadCombine.scala b/core/src/main/scala/cats/MonadCombine.scala index a418cba774..8505c77478 100644 --- a/core/src/main/scala/cats/MonadCombine.scala +++ b/core/src/main/scala/cats/MonadCombine.scala @@ -5,7 +5,10 @@ import simulacrum.typeclass /** * The combination of a Monad with a MonoidK */ -@typeclass trait MonadCombine[F[_]] extends MonadFilter[F] with Alternative[F] { +@typeclass trait MonadCombine[F[_]] extends Monad[F] with FunctorFilter[F] with Alternative[F] { + + override def mapFilter[A, B](fa: F[A])(f: A => Option[B]): F[B] = + flatMap(fa)(a => f(a).fold(empty[B])(pure)) /** * Fold over the inner structure to combine all of the values with diff --git a/core/src/main/scala/cats/MonadFilter.scala b/core/src/main/scala/cats/MonadFilter.scala deleted file mode 100644 index e2099a49e2..0000000000 --- a/core/src/main/scala/cats/MonadFilter.scala +++ /dev/null @@ -1,18 +0,0 @@ -package cats - -import simulacrum.typeclass - -/** - * a Monad equipped with an additional method which allows us to - * create an "empty" value for the Monad (for whatever "empty" makes - * sense for that particular monad). This is of particular interest to - * us since it allows us to add a `filter` method to a Monad, which is - * used when pattern matching or using guards in for comprehensions. - */ -@typeclass trait MonadFilter[F[_]] extends Monad[F] with FunctorFilter[F] { - - def empty[A]: F[A] - - override def mapFilter[A, B](fa: F[A])(f: A => Option[B]): F[B] = - flatMap(fa)(a => f(a).fold(empty[B])(pure)) -} diff --git a/core/src/main/scala/cats/data/EitherT.scala b/core/src/main/scala/cats/data/EitherT.scala index 38eab701fe..0b11038981 100644 --- a/core/src/main/scala/cats/data/EitherT.scala +++ b/core/src/main/scala/cats/data/EitherT.scala @@ -314,14 +314,6 @@ private[data] abstract class EitherTInstances extends EitherTInstances1 { } private[data] abstract class EitherTInstances1 extends EitherTInstances2 { - /* TODO violates monadFilter right empty law -- re-enable when MonadFilter laws are split in to weak/strong - implicit def catsDataMonadFilterForEitherT[F[_], L](implicit F: Monad[F], L: Monoid[L]): MonadFilter[EitherT[F, L, ?]] = { - implicit val F0 = F - implicit val L0 = L - new EitherTMonadFilter[F, L] { implicit val F = F0; implicit val L = L0 } - } - */ - implicit def catsSemigroupForEitherT[F[_], L, A](implicit F: Semigroup[F[Either[L, A]]]): Semigroup[EitherT[F, L, A]] = new EitherTSemigroup[F, L, A] { implicit val F0 = F } @@ -418,12 +410,6 @@ private[data] trait EitherTMonadError[F[_], L] extends MonadError[EitherT[F, L, fla.recoverWith(pf) } -private[data] trait EitherTMonadFilter[F[_], L] extends MonadFilter[EitherT[F, L, ?]] with EitherTMonadError[F, L] { - implicit val F: Monad[F] - implicit val L: Monoid[L] - def empty[A]: EitherT[F, L, A] = EitherT(F.pure(Either.left(L.empty))) -} - /* TODO violates right absorbtion, right distributivity, and left distributivity -- re-enable when MonadCombine laws are split in to weak/strong private[data] trait EitherTMonadCombine[F[_], L] extends MonadCombine[EitherT[F, L, ?]] with EitherTMonadFilter[F, L] with EitherTSemigroupK[F, L] { implicit val F: Monad[F] diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index 9c85d97f52..c95062a6db 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -113,12 +113,6 @@ private[data] sealed abstract class WriterTInstances0 extends WriterTInstances1 } private[data] sealed abstract class WriterTInstances1 extends WriterTInstances2 { - implicit def catsDataMonadFilterForWriterT[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 - } - implicit def catsDataMonoidForWriterT[F[_], L, V](implicit W: Monoid[F[(L, V)]]): Monoid[WriterT[F, L, V]] = new WriterTMonoid[F, L, V] { implicit val F0: Monoid[F[(L, V)]] = W @@ -359,12 +353,6 @@ private[data] sealed trait WriterTAlternative[F[_], L] extends Alternative[Write 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] } diff --git a/core/src/main/scala/cats/syntax/all.scala b/core/src/main/scala/cats/syntax/all.scala index b37414961e..f307f6e492 100644 --- a/core/src/main/scala/cats/syntax/all.scala +++ b/core/src/main/scala/cats/syntax/all.scala @@ -25,7 +25,6 @@ trait AllSyntax with ListSyntax with MonadCombineSyntax with MonadErrorSyntax - with MonadFilterSyntax with MonoidSyntax with OptionSyntax with OrderSyntax diff --git a/core/src/main/scala/cats/syntax/monadFilter.scala b/core/src/main/scala/cats/syntax/monadFilter.scala deleted file mode 100644 index 21c98a869b..0000000000 --- a/core/src/main/scala/cats/syntax/monadFilter.scala +++ /dev/null @@ -1,12 +0,0 @@ -package cats -package syntax - -private[syntax] trait MonadFilterSyntax1 { - implicit def catsSyntaxUMonadFilter[FA](fa: FA)(implicit U: Unapply[MonadFilter, FA]): MonadFilter.Ops[U.M, U.A] = - new MonadFilter.Ops[U.M, U.A] { - val self = U.subst(fa) - val typeClassInstance = U.TC - } -} - -trait MonadFilterSyntax extends MonadFilter.ToMonadFilterOps with MonadFilterSyntax1 diff --git a/core/src/main/scala/cats/syntax/package.scala b/core/src/main/scala/cats/syntax/package.scala index c54dd449e7..40bfdcf402 100644 --- a/core/src/main/scala/cats/syntax/package.scala +++ b/core/src/main/scala/cats/syntax/package.scala @@ -24,7 +24,6 @@ package object syntax { object invariant extends InvariantSyntax object list extends ListSyntax object monadCombine extends MonadCombineSyntax - object monadFilter extends MonadFilterSyntax object monoid extends MonoidSyntax object option extends OptionSyntax object order extends OrderSyntax diff --git a/docs/src/main/tut/monadfilter.md b/docs/src/main/tut/monadfilter.md deleted file mode 100644 index 595bf9f98b..0000000000 --- a/docs/src/main/tut/monadfilter.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -layout: default -title: "MonadFilter" -section: "typeclasses" -source: "core/src/main/scala/cats/MonadFilter.scala" -scaladoc: "#cats.MonadFilter" ---- -# MonadFilter - diff --git a/laws/src/main/scala/cats/laws/MonadCombineLaws.scala b/laws/src/main/scala/cats/laws/MonadCombineLaws.scala index a8100e381d..2ff7b640f3 100644 --- a/laws/src/main/scala/cats/laws/MonadCombineLaws.scala +++ b/laws/src/main/scala/cats/laws/MonadCombineLaws.scala @@ -6,9 +6,18 @@ import cats.syntax.all._ /** * Laws that must be obeyed by any `MonadCombine`. */ -trait MonadCombineLaws[F[_]] extends MonadFilterLaws[F] with AlternativeLaws[F] { +trait MonadCombineLaws[F[_]] extends MonadLaws[F] with FunctorFilterLaws[F] with AlternativeLaws[F] { implicit override def F: MonadCombine[F] + def monadCombineLeftEmpty[A, B](f: A => F[B]): IsEq[F[B]] = + F.empty[A].flatMap(f) <-> F.empty[B] + + def monadCombineRightEmpty[A, B](fa: F[A]): IsEq[F[B]] = + fa.flatMap(_ => F.empty[B]) <-> F.empty[B] + + def monadCombineConsistency[A, B](fa: F[A], f: A => Boolean): IsEq[F[A]] = + fa.filter(f) <-> fa.flatMap(a => if (f(a)) F.pure(a) else F.empty) + def monadCombineLeftDistributivity[A, B](fa: F[A], fa2: F[A], f: A => F[B]): IsEq[F[B]] = F.combineK(fa, fa2).flatMap(f) <-> F.combineK(fa flatMap f, fa2 flatMap f) } diff --git a/laws/src/main/scala/cats/laws/MonadFilterLaws.scala b/laws/src/main/scala/cats/laws/MonadFilterLaws.scala deleted file mode 100644 index 9116df2bba..0000000000 --- a/laws/src/main/scala/cats/laws/MonadFilterLaws.scala +++ /dev/null @@ -1,25 +0,0 @@ -package cats -package laws - -import cats.syntax.all._ - -/** - * Laws that must be obeyed by any `MonadFilter`. - */ -trait MonadFilterLaws[F[_]] extends MonadLaws[F] with FunctorFilterLaws[F] { - implicit override def F: MonadFilter[F] - - def monadFilterLeftEmpty[A, B](f: A => F[B]): IsEq[F[B]] = - F.empty[A].flatMap(f) <-> F.empty[B] - - def monadFilterRightEmpty[A, B](fa: F[A]): IsEq[F[B]] = - fa.flatMap(_ => F.empty[B]) <-> F.empty[B] - - def monadFilterConsistency[A, B](fa: F[A], f: A => Boolean): IsEq[F[A]] = - fa.filter(f) <-> fa.flatMap(a => if (f(a)) F.pure(a) else F.empty) -} - -object MonadFilterLaws { - def apply[F[_]](implicit ev: MonadFilter[F]): MonadFilterLaws[F] = - new MonadFilterLaws[F] { def F: MonadFilter[F] = ev } -} diff --git a/laws/src/main/scala/cats/laws/discipline/MonadCombineTests.scala b/laws/src/main/scala/cats/laws/discipline/MonadCombineTests.scala index be6ec6ed11..a23546b367 100644 --- a/laws/src/main/scala/cats/laws/discipline/MonadCombineTests.scala +++ b/laws/src/main/scala/cats/laws/discipline/MonadCombineTests.scala @@ -7,7 +7,7 @@ import org.scalacheck.Arbitrary import org.scalacheck.Prop import Prop._ -trait MonadCombineTests[F[_]] extends MonadFilterTests[F] with AlternativeTests[F] { +trait MonadCombineTests[F[_]] extends MonadTests[F] with FunctorFilterTests[F] with AlternativeTests[F] { def laws: MonadCombineLaws[F] def monadCombine[A: Arbitrary: Eq, B: Arbitrary: Eq, C: Arbitrary: Eq](implicit @@ -25,8 +25,11 @@ trait MonadCombineTests[F[_]] extends MonadFilterTests[F] with AlternativeTests[ new RuleSet { def name: String = "monadCombine" def bases: Seq[(String, RuleSet)] = Nil - def parents: Seq[RuleSet] = Seq(monadFilter[A, B, C], alternative[A, B, C]) + def parents: Seq[RuleSet] = Seq(monad[A, B, C], functorFilter[A, B, C], alternative[A, B, C]) def props: Seq[(String, Prop)] = Seq( + "monadCombine left empty" -> forAll(laws.monadCombineLeftEmpty[A, B] _), + "monadCombine right empty" -> forAll(laws.monadCombineRightEmpty[A, B] _), + "monadCombine consistency" -> forAll(laws.monadCombineConsistency[A, B] _), "monadCombine left distributivity" -> forAll(laws.monadCombineLeftDistributivity[A, B] _) ) } diff --git a/laws/src/main/scala/cats/laws/discipline/MonadFilterTests.scala b/laws/src/main/scala/cats/laws/discipline/MonadFilterTests.scala deleted file mode 100644 index bfdb555fd6..0000000000 --- a/laws/src/main/scala/cats/laws/discipline/MonadFilterTests.scala +++ /dev/null @@ -1,43 +0,0 @@ -package cats -package laws -package discipline - -import cats.laws.discipline.CartesianTests.Isomorphisms -import org.scalacheck.Arbitrary -import org.scalacheck.Prop -import Prop._ - -trait MonadFilterTests[F[_]] extends MonadTests[F] with FunctorFilterTests[F] { - def laws: MonadFilterLaws[F] - - def monadFilter[A: Arbitrary: Eq, B: Arbitrary: Eq, C: Arbitrary: Eq](implicit - ArbFA: Arbitrary[F[A]], - ArbFB: Arbitrary[F[B]], - ArbFC: Arbitrary[F[C]], - ArbFAtoB: Arbitrary[F[A => B]], - ArbFBtoC: Arbitrary[F[B => C]], - EqFA: Eq[F[A]], - EqFB: Eq[F[B]], - EqFC: Eq[F[C]], - EqFABC: Eq[F[(A, B, C)]], - iso: Isomorphisms[F] - ): RuleSet = { - new RuleSet { - def name: String = "monadFilter" - def bases: Seq[(String, RuleSet)] = Nil - def parents: Seq[RuleSet] = Seq(monad[A, B, C], functorFilter[A, B, C]) - def props: Seq[(String, Prop)] = Seq( - "monadFilter left empty" -> forAll(laws.monadFilterLeftEmpty[A, B] _), - "monadFilter right empty" -> forAll(laws.monadFilterRightEmpty[A, B] _), - "monadFilter consistency" -> forAll(laws.monadFilterConsistency[A, B] _) - ) - } - } -} - -object MonadFilterTests { - def apply[F[_]: MonadFilter]: MonadFilterTests[F] = - new MonadFilterTests[F] { - def laws: MonadFilterLaws[F] = MonadFilterLaws[F] - } -} diff --git a/tests/src/test/scala/cats/tests/ListWrapper.scala b/tests/src/test/scala/cats/tests/ListWrapper.scala index 4c2dad7efa..39bd1e32b7 100644 --- a/tests/src/test/scala/cats/tests/ListWrapper.scala +++ b/tests/src/test/scala/cats/tests/ListWrapper.scala @@ -104,8 +104,6 @@ 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] diff --git a/tests/src/test/scala/cats/tests/WriterTTests.scala b/tests/src/test/scala/cats/tests/WriterTTests.scala index b41c680b23..01d54c7983 100644 --- a/tests/src/test/scala/cats/tests/WriterTTests.scala +++ b/tests/src/test/scala/cats/tests/WriterTTests.scala @@ -293,21 +293,6 @@ class WriterTTests extends CatsSuite { 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], ?]] - CoflatMap[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 @@ -319,7 +304,6 @@ class WriterTTests extends CatsSuite { FlatMap[WriterT[ListWrapper, ListWrapper[Int], ?]] CoflatMap[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], ?]]