From ec1f60416180b5b48e075b003f76a794f934622d Mon Sep 17 00:00:00 2001 From: Luka Jacobowitz Date: Sun, 10 Dec 2017 02:10:29 +0100 Subject: [PATCH 01/18] Add InvariantSemigroupal and ability to turn Monoidals to Monoids --- .../scala/cats/ContravariantMonoidal.scala | 9 +++++- .../scala/cats/ContravariantSemigroupal.scala | 11 +++++++- .../main/scala/cats/InvariantMonoidal.scala | 11 +++++++- .../scala/cats/InvariantSemigroupal.scala | 28 +++++++++++++++++++ 4 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 core/src/main/scala/cats/InvariantSemigroupal.scala diff --git a/core/src/main/scala/cats/ContravariantMonoidal.scala b/core/src/main/scala/cats/ContravariantMonoidal.scala index f4f6881436..ec273deb7c 100644 --- a/core/src/main/scala/cats/ContravariantMonoidal.scala +++ b/core/src/main/scala/cats/ContravariantMonoidal.scala @@ -19,4 +19,11 @@ import simulacrum.typeclass */ def unit[A]: F[A] } -object ContravariantMonoidal extends SemigroupalArityFunctions +object ContravariantMonoidal extends SemigroupalArityFunctions { + def monoid[F[_], A](implicit f: ContravariantMonoidal[F], monoid: Monoid[A]): Monoid[F[A]] = + new ContravariantMonoidalMonoid[F, A](f) +} + +private[cats] class ContravariantMonoidalMonoid[F[_], A](f: ContravariantMonoidal[F]) extends ContravariantSemigroupalSemigroup[F, A](f) with Monoid[F[A]] { + def empty: F[A] = f.unit +} diff --git a/core/src/main/scala/cats/ContravariantSemigroupal.scala b/core/src/main/scala/cats/ContravariantSemigroupal.scala index d641fe9067..7a41095334 100644 --- a/core/src/main/scala/cats/ContravariantSemigroupal.scala +++ b/core/src/main/scala/cats/ContravariantSemigroupal.scala @@ -13,4 +13,13 @@ import simulacrum.typeclass def G = Functor[G] } } -object ContravariantSemigroupal extends SemigroupalArityFunctions + +object ContravariantSemigroupal extends SemigroupalArityFunctions { + def semigroup[F[_], A](implicit f: ContravariantSemigroupal[F]): Semigroup[F[A]] = + new ContravariantSemigroupalSemigroup[F, A](f) +} + +private[cats] class ContravariantSemigroupalSemigroup[F[_], A](f: ContravariantSemigroupal[F]) extends Semigroup[F[A]] { + def combine(a: F[A], b: F[A]): F[A] = + ContravariantSemigroupal.contramap2(a, b)((a: A) => (a, a))(f, f) +} diff --git a/core/src/main/scala/cats/InvariantMonoidal.scala b/core/src/main/scala/cats/InvariantMonoidal.scala index 37c3ada5de..08381b1ec9 100644 --- a/core/src/main/scala/cats/InvariantMonoidal.scala +++ b/core/src/main/scala/cats/InvariantMonoidal.scala @@ -7,6 +7,15 @@ import simulacrum.typeclass * * Must obey the laws defined in cats.laws.InvariantMonoidalLaws. */ -@typeclass trait InvariantMonoidal[F[_]] extends Invariant[F] with Semigroupal[F] { +@typeclass trait InvariantMonoidal[F[_]] extends InvariantSemigroupal[F] { def pure[A](a: A): F[A] } + +object InvariantMonoidal { + def monoid[F[_], A](implicit f: InvariantMonoidal[F], monoid: Monoid[A]): Monoid[F[A]] = + new InvariantMonoidalMonoid[F, A](f, monoid) +} + +private[cats] class InvariantMonoidalMonoid[F[_], A](f: InvariantMonoidal[F], monoid: Monoid[A]) extends InvariantSemigroupalSemigroup(f, monoid) with Monoid[F[A]] { + def empty: F[A] = f.pure(monoid.empty) +} diff --git a/core/src/main/scala/cats/InvariantSemigroupal.scala b/core/src/main/scala/cats/InvariantSemigroupal.scala new file mode 100644 index 0000000000..54010b873d --- /dev/null +++ b/core/src/main/scala/cats/InvariantSemigroupal.scala @@ -0,0 +1,28 @@ +package cats + +import simulacrum.typeclass + +/** + * [[InvariantSemigroupal]] is nothing more than something both invariant + * and Semigroupal. It comes up enough to be useful, and composes well + */ +@typeclass trait InvariantSemigroupal[F[_]] extends Semigroupal[F] with Invariant[F] { self => + /* + override def composeFunctor[G[_]: Functor]: InvariantSemigroupal[λ[α => F[G[α]]]] = + new ComposedSemigroupal[F, G] { + def F = self + def G = Functor[G] + } + + */ +} + +object InvariantSemigroupal extends SemigroupalArityFunctions { + def semigroup[F[_], A](implicit f: InvariantSemigroupal[F], sg: Semigroup[A]): Semigroup[F[A]] = + new InvariantSemigroupalSemigroup[F, A](f, sg) +} + +private[cats] class InvariantSemigroupalSemigroup[F[_], A](f: InvariantSemigroupal[F], sg: Semigroup[A]) extends Semigroup[F[A]] { + def combine(a: F[A], b: F[A]): F[A] = + InvariantSemigroupal.imap2(a, b)(sg.combine)(a => (a, a))(f, f) +} From 2edcb854b12154dddfdbf2dbdfb66418cd54d87f Mon Sep 17 00:00:00 2001 From: Luka Jacobowitz Date: Sun, 10 Dec 2017 11:31:50 +0100 Subject: [PATCH 02/18] Add Tests --- .../scala/cats/tests/ContravariantSuite.scala | 29 +++++++++++++++++++ .../CsvCodecInvariantMonoidalSuite.scala | 6 ++++ 2 files changed, 35 insertions(+) diff --git a/tests/src/test/scala/cats/tests/ContravariantSuite.scala b/tests/src/test/scala/cats/tests/ContravariantSuite.scala index c7007b0f8b..e18add48fd 100644 --- a/tests/src/test/scala/cats/tests/ContravariantSuite.scala +++ b/tests/src/test/scala/cats/tests/ContravariantSuite.scala @@ -2,7 +2,11 @@ package cats package tests import cats.data.Const +import cats.kernel.laws.discipline.MonoidTests +import cats.laws.discipline.ContravariantMonoidalTests import org.scalactic.CanEqual +import org.scalacheck.{Arbitrary, Cogen} +import cats.laws.discipline.eq._ class ContravariantSuite extends CatsSuite { @@ -18,4 +22,29 @@ class ContravariantSuite extends CatsSuite { } } + case class Predicate[A](run: A => Boolean) + + implicit val contravariantMonoidalPredicate: ContravariantMonoidal[Predicate] = + new ContravariantMonoidal[Predicate] { + def unit[A]: Predicate[A] = Predicate[A](Function.const(true)) + def product[A, B](fa: Predicate[A], fb: Predicate[B]): Predicate[(A, B)] = + Predicate(x => fa.run(x._1) && fb.run(x._2)) + def contramap[A, B](fa: Predicate[A])(f: B => A): Predicate[B] = + Predicate(x => fa.run(f(x))) + } + + implicit def eqPredicate[A: Arbitrary]: Eq[Predicate[A]] = + Eq.by[Predicate[A], A => Boolean](_.run) + + + implicit def arbPredicate[A: Cogen]: Arbitrary[Predicate[A]] = + Arbitrary(implicitly[Arbitrary[A => Boolean]].arbitrary.map(f => Predicate(f))) + + checkAll("ContravariantMonoidal[Predicate]", ContravariantMonoidalTests[Predicate].contravariantMonoidal[Int, Int, Int]) + + { + implicit val predicateMonoid = ContravariantMonoidal.monoid[Predicate, Int] + checkAll("ContravariantMonoidal[Predicate].monoid", MonoidTests[Predicate[Int]].monoid) + } + } diff --git a/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala b/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala index 37d0a3b0ec..2957f9c071 100644 --- a/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala +++ b/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala @@ -6,6 +6,7 @@ import cats.laws.discipline.{InvariantMonoidalTests, SerializableTests} import cats.instances.all._ import cats.syntax.apply._ import cats.Eq +import cats.kernel.laws.discipline.MonoidTests import org.scalacheck.{Arbitrary, Gen} object CsvCodecInvariantMonoidalSuite { @@ -92,4 +93,9 @@ class CsvCodecInvariantMonoidalSuite extends CatsSuite { checkAll("InvariantMonoidal[CsvCodec]", InvariantMonoidalTests[CsvCodec].invariantMonoidal[Int, Int, Int]) checkAll("InvariantMonoidal[CsvCodec]", SerializableTests.serializable(InvariantMonoidal[CsvCodec])) + + { + implicit val csvMonoid = InvariantMonoidal.monoid[CsvCodec, Int] + checkAll("InvariantMonoidal[CsvCodec].monoid", MonoidTests[CsvCodec[Int]].monoid) + } } From 495cc7455b43077dc4c991885f89899134a8bc89 Mon Sep 17 00:00:00 2001 From: Luka Jacobowitz Date: Sun, 10 Dec 2017 12:08:25 +0100 Subject: [PATCH 03/18] Add composition with Apply --- core/src/main/scala/cats/Composed.scala | 12 ++++++++++++ .../src/main/scala/cats/InvariantSemigroupal.scala | 14 +++++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/core/src/main/scala/cats/Composed.scala b/core/src/main/scala/cats/Composed.scala index 0a6953e7be..3d445c020e 100644 --- a/core/src/main/scala/cats/Composed.scala +++ b/core/src/main/scala/cats/Composed.scala @@ -136,6 +136,18 @@ private[cats] trait ComposedSemigroupal[F[_], G[_]] extends ContravariantSemigro } } +private[cats] trait ComposedInvariantApplySemigroupal[F[_], G[_]] extends InvariantSemigroupal[λ[α => F[G[α]]]] with ComposedInvariantCovariant[F, G] { outer => + def F: InvariantSemigroupal[F] + def G: Apply[G] + + def product[A, B](fa: F[G[A]], fb: F[G[B]]): F[G[(A, B)]] = + F.imap(F.product(fa, fb)) { case (ga, gb) => + G.map2(ga, gb)(_ -> _) + } { g: G[(A, B)] => + (G.map(g)(_._1), G.map(g)(_._2)) + } +} + private[cats] trait ComposedCovariantContravariant[F[_], G[_]] extends Contravariant[λ[α => F[G[α]]]] { outer => def F: Functor[F] def G: Contravariant[G] diff --git a/core/src/main/scala/cats/InvariantSemigroupal.scala b/core/src/main/scala/cats/InvariantSemigroupal.scala index 54010b873d..cbc467d3fb 100644 --- a/core/src/main/scala/cats/InvariantSemigroupal.scala +++ b/core/src/main/scala/cats/InvariantSemigroupal.scala @@ -7,14 +7,14 @@ import simulacrum.typeclass * and Semigroupal. It comes up enough to be useful, and composes well */ @typeclass trait InvariantSemigroupal[F[_]] extends Semigroupal[F] with Invariant[F] { self => - /* - override def composeFunctor[G[_]: Functor]: InvariantSemigroupal[λ[α => F[G[α]]]] = - new ComposedSemigroupal[F, G] { - def F = self - def G = Functor[G] - } - */ + def composeApply[G[_]: Apply]: InvariantSemigroupal[λ[α => F[G[α]]]] = + new ComposedInvariantApplySemigroupal[F, G] { + def F = self + def G = Apply[G] + } + + } object InvariantSemigroupal extends SemigroupalArityFunctions { From d8b496d8e9909acd4c8b3a9cd10497abdc8dfa35 Mon Sep 17 00:00:00 2001 From: Luka Jacobowitz Date: Sun, 10 Dec 2017 12:47:56 +0100 Subject: [PATCH 04/18] Add Mima exception --- build.sbt | 1 + 1 file changed, 1 insertion(+) diff --git a/build.sbt b/build.sbt index c16c1803c2..781310b18d 100644 --- a/build.sbt +++ b/build.sbt @@ -322,6 +322,7 @@ def mimaSettings(moduleName: String) = Seq( exclude[DirectMissingMethodProblem]("cats.data.RWSTAlternative.sequence"), exclude[ReversedMissingMethodProblem]("cats.MonadError.rethrow"), exclude[ReversedMissingMethodProblem]("cats.syntax.MonadErrorSyntax.catsSyntaxMonadErrorRethrow"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.composeApply"), exclude[DirectMissingMethodProblem]("cats.data.CokleisliArrow.id"), exclude[IncompatibleResultTypeProblem]("cats.data.CokleisliArrow.id") ) From 19dc0ffeb0a1a55af6e5b9fdb31b55dd3c2238b9 Mon Sep 17 00:00:00 2001 From: Luka Jacobowitz Date: Tue, 12 Dec 2017 11:57:44 +0100 Subject: [PATCH 05/18] More tests + Nested --- .../scala/cats/InvariantSemigroupal.scala | 13 +++++++ core/src/main/scala/cats/Semigroupal.scala | 9 +---- core/src/main/scala/cats/data/Nested.scala | 23 +++++++++++-- .../cats/laws/InvariantMonoidalLaws.scala | 2 +- .../cats/laws/InvariantSemigroupalLaws.scala | 15 ++++++++ .../discipline/InvariantMonoidalTests.scala | 2 +- .../InvariantSemigroupalTests.scala | 34 +++++++++++++++++++ .../cats/tests/AlgebraInvariantSuite.scala | 4 +-- .../test/scala/cats/tests/ListWrapper.scala | 9 ++--- .../test/scala/cats/tests/MonoidSuite.scala | 4 +-- .../test/scala/cats/tests/NestedSuite.scala | 9 +++++ 11 files changed, 103 insertions(+), 21 deletions(-) create mode 100644 laws/src/main/scala/cats/laws/InvariantSemigroupalLaws.scala create mode 100644 laws/src/main/scala/cats/laws/discipline/InvariantSemigroupalTests.scala diff --git a/core/src/main/scala/cats/InvariantSemigroupal.scala b/core/src/main/scala/cats/InvariantSemigroupal.scala index cbc467d3fb..9e6b59d7be 100644 --- a/core/src/main/scala/cats/InvariantSemigroupal.scala +++ b/core/src/main/scala/cats/InvariantSemigroupal.scala @@ -20,6 +20,19 @@ import simulacrum.typeclass object InvariantSemigroupal extends SemigroupalArityFunctions { def semigroup[F[_], A](implicit f: InvariantSemigroupal[F], sg: Semigroup[A]): Semigroup[F[A]] = new InvariantSemigroupalSemigroup[F, A](f, sg) + + implicit def catsSemigroupalForMonoid: InvariantSemigroupal[Monoid] = new InvariantSemigroupal[Monoid] { + def product[A, B](fa: Monoid[A], fb: Monoid[B]): Monoid[(A, B)] = new Monoid[(A, B)] { + val empty = fa.empty -> fb.empty + def combine(x: (A, B), y: (A, B)): (A, B) = fa.combine(x._1, y._1) -> fb.combine(x._2, y._2) + } + + def imap[A, B](fa: Monoid[A])(f: A => B)(g: B => A): Monoid[B] = new Monoid[B] { + def empty: B = f(fa.empty) + + def combine(x: B, y: B): B = f(fa.combine(g(x), g(y))) + } + } } private[cats] class InvariantSemigroupalSemigroup[F[_], A](f: InvariantSemigroupal[F], sg: Semigroup[A]) extends Semigroup[F[A]] { diff --git a/core/src/main/scala/cats/Semigroupal.scala b/core/src/main/scala/cats/Semigroupal.scala index 70d10ace51..6fed1ca0e9 100644 --- a/core/src/main/scala/cats/Semigroupal.scala +++ b/core/src/main/scala/cats/Semigroupal.scala @@ -16,11 +16,4 @@ import simulacrum.typeclass def product[A, B](fa: F[A], fb: F[B]): F[(A, B)] } -object Semigroupal extends SemigroupalArityFunctions { - implicit def catsSemigroupalForMonoid: Semigroupal[Monoid] = new Semigroupal[Monoid] { - def product[A, B](fa: Monoid[A], fb: Monoid[B]): Monoid[(A, B)] = new Monoid[(A, B)] { - val empty = fa.empty -> fb.empty - def combine(x: (A, B), y: (A, B)): (A, B) = fa.combine(x._1, y._1) -> fb.combine(x._2, y._2) - } - } -} +object Semigroupal extends SemigroupalArityFunctions diff --git a/core/src/main/scala/cats/data/Nested.scala b/core/src/main/scala/cats/data/Nested.scala index 1d8aef27c5..1538a527d2 100644 --- a/core/src/main/scala/cats/data/Nested.scala +++ b/core/src/main/scala/cats/data/Nested.scala @@ -142,27 +142,34 @@ private[data] sealed abstract class NestedInstances8 extends NestedInstances9 { } private[data] sealed abstract class NestedInstances9 extends NestedInstances10 { + implicit def catsDataInvariantSemigroupalApplyForNested[F[_]: InvariantSemigroupal, G[_]: Apply]: InvariantSemigroupal[Nested[F, G, ?]] = + new NestedInvariantSemigroupalApply[F, G] { + val FG: InvariantSemigroupal[λ[α => F[G[α]]]] = InvariantSemigroupal[F].composeApply[G] + } +} + +private[data] sealed abstract class NestedInstances10 extends NestedInstances11 { implicit def catsDataFunctorForNested[F[_]: Functor, G[_]: Functor]: Functor[Nested[F, G, ?]] = new NestedFunctor[F, G] { val FG: Functor[λ[α => F[G[α]]]] = Functor[F].compose[G] } } -private[data] sealed abstract class NestedInstances10 extends NestedInstances11 { +private[data] sealed abstract class NestedInstances11 extends NestedInstances12 { implicit def catsDataInvariantForNested[F[_]: Invariant, G[_]: Invariant]: Invariant[Nested[F, G, ?]] = new NestedInvariant[F, G] { val FG: Invariant[λ[α => F[G[α]]]] = Invariant[F].compose[G] } } -private[data] sealed abstract class NestedInstances11 extends NestedInstances12 { +private[data] sealed abstract class NestedInstances12 extends NestedInstances13 { implicit def catsDataInvariantForCovariantNested[F[_]: Invariant, G[_]: Functor]: Invariant[Nested[F, G, ?]] = new NestedInvariant[F, G] { val FG: Invariant[λ[α => F[G[α]]]] = Invariant[F].composeFunctor[G] } } -private[data] sealed abstract class NestedInstances12 { +private[data] sealed abstract class NestedInstances13 { implicit def catsDataInvariantForNestedContravariant[F[_]: Invariant, G[_]: Contravariant]: Invariant[Nested[F, G, ?]] = new NestedInvariant[F, G] { val FG: Invariant[λ[α => F[G[α]]]] = Invariant[F].composeContravariant[G] @@ -280,3 +287,13 @@ private[data] trait NestedContravariantMonoidal[F[_], G[_]] extends Contravarian def product[A, B](fa: Nested[F, G, A], fb: Nested[F, G, B]): Nested[F, G, (A, B)] = Nested(FG.product(fa.value, fb.value)) } + +private[data] trait NestedInvariantSemigroupalApply[F[_], G[_]] extends InvariantSemigroupal[Nested[F, G, ?]] { + def FG: InvariantSemigroupal[λ[α => F[G[α]]]] + + def imap[A, B](fa: Nested[F, G, A])(f: A => B)(g: B => A): Nested[F, G, B] = + Nested(FG.imap(fa.value)(f)(g)) + + def product[A, B](fa: Nested[F, G, A], fb: Nested[F, G, B]): Nested[F, G, (A, B)] = + Nested(FG.product(fa.value, fb.value)) +} diff --git a/laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala b/laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala index 99ed3761ce..f973ec3295 100644 --- a/laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala +++ b/laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala @@ -4,7 +4,7 @@ package laws /** * Laws that must be obeyed by any `cats.InvariantMonoidal`. */ -trait InvariantMonoidalLaws[F[_]] extends InvariantLaws[F] with SemigroupalLaws[F] { +trait InvariantMonoidalLaws[F[_]] extends InvariantSemigroupalLaws[F] { override implicit def F: InvariantMonoidal[F] import cats.syntax.semigroupal._ import cats.syntax.invariant._ diff --git a/laws/src/main/scala/cats/laws/InvariantSemigroupalLaws.scala b/laws/src/main/scala/cats/laws/InvariantSemigroupalLaws.scala new file mode 100644 index 0000000000..f1c301787c --- /dev/null +++ b/laws/src/main/scala/cats/laws/InvariantSemigroupalLaws.scala @@ -0,0 +1,15 @@ +package cats +package laws + + +/** + * Laws that are expected for any `cats.InvariantSemigroupal`. + */ +trait InvariantSemigroupalLaws[F[_]] extends InvariantLaws[F] with SemigroupalLaws[F] { + implicit override def F: InvariantSemigroupal[F] + +} +object InvariantSemigroupalLaws { + def apply[F[_]](implicit ev: InvariantSemigroupal[F]): InvariantSemigroupalLaws[F] = + new InvariantSemigroupalLaws[F] { def F: InvariantSemigroupal[F] = ev } +} diff --git a/laws/src/main/scala/cats/laws/discipline/InvariantMonoidalTests.scala b/laws/src/main/scala/cats/laws/discipline/InvariantMonoidalTests.scala index e68f46a12b..c9240c8d37 100644 --- a/laws/src/main/scala/cats/laws/discipline/InvariantMonoidalTests.scala +++ b/laws/src/main/scala/cats/laws/discipline/InvariantMonoidalTests.scala @@ -6,7 +6,7 @@ import cats.laws.discipline.SemigroupalTests.Isomorphisms import org.scalacheck.{Arbitrary, Cogen} import org.scalacheck.Prop._ -trait InvariantMonoidalTests[F[_]] extends InvariantTests[F] with SemigroupalTests[F] { +trait InvariantMonoidalTests[F[_]] extends InvariantSemigroupalTests[F] { def laws: InvariantMonoidalLaws[F] def invariantMonoidal[A: Arbitrary, B: Arbitrary, C: Arbitrary](implicit diff --git a/laws/src/main/scala/cats/laws/discipline/InvariantSemigroupalTests.scala b/laws/src/main/scala/cats/laws/discipline/InvariantSemigroupalTests.scala new file mode 100644 index 0000000000..3eae12a930 --- /dev/null +++ b/laws/src/main/scala/cats/laws/discipline/InvariantSemigroupalTests.scala @@ -0,0 +1,34 @@ +package cats +package laws +package discipline + +import cats.InvariantSemigroupal +import cats.laws.discipline.SemigroupalTests.Isomorphisms +import org.scalacheck.{Arbitrary, Cogen} + +trait InvariantSemigroupalTests[F[_]] extends InvariantTests[F] with SemigroupalTests[F] { + def laws: InvariantSemigroupalLaws[F] + + def invariantSemigroupal[A: Arbitrary, B: Arbitrary, C: Arbitrary](implicit + arbFA: Arbitrary[F[A]], + arbFB: Arbitrary[F[B]], + arbFC: Arbitrary[F[C]], + CogenA: Cogen[A], + CogenB: Cogen[B], + CogenC: Cogen[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 { + val name = "invariantSemigroupal" + val parents = Seq(invariant[A, B, C], semigroupal[A, B, C]) + val bases = Nil + val props = Nil + } +} + +object InvariantSemigroupalTests { + def apply[F[_]: InvariantSemigroupal]: InvariantSemigroupalTests[F] = + new InvariantSemigroupalTests[F] { def laws: InvariantSemigroupalLaws[F] = InvariantSemigroupalLaws[F] } +} diff --git a/tests/src/test/scala/cats/tests/AlgebraInvariantSuite.scala b/tests/src/test/scala/cats/tests/AlgebraInvariantSuite.scala index f9305c294d..82faf03440 100644 --- a/tests/src/test/scala/cats/tests/AlgebraInvariantSuite.scala +++ b/tests/src/test/scala/cats/tests/AlgebraInvariantSuite.scala @@ -4,7 +4,7 @@ package tests import cats.Invariant import cats.kernel._ import cats.kernel.laws.discipline.{SemigroupTests, MonoidTests, GroupTests, _} -import cats.laws.discipline.{InvariantMonoidalTests, InvariantTests, SerializableTests, SemigroupalTests} +import cats.laws.discipline.{InvariantMonoidalTests, InvariantTests, SerializableTests, InvariantSemigroupalTests} import cats.laws.discipline.eq._ import org.scalacheck.{Arbitrary, Gen} @@ -64,7 +64,7 @@ class AlgebraInvariantSuite extends CatsSuite { checkAll("InvariantMonoidal[Semigroup]", SemigroupTests[Int](InvariantMonoidal[Semigroup].pure(0)).semigroup) checkAll("InvariantMonoidal[CommutativeSemigroup]", CommutativeSemigroupTests[Int](InvariantMonoidal[CommutativeSemigroup].pure(0)).commutativeSemigroup) - checkAll("Semigroupal[Monoid]", SemigroupalTests[Monoid].semigroupal[Int, Int, Int]) + checkAll("InvariantSemigroupal[Monoid]", InvariantSemigroupalTests[Monoid].invariantSemigroupal[Int, Int, Int]) { diff --git a/tests/src/test/scala/cats/tests/ListWrapper.scala b/tests/src/test/scala/cats/tests/ListWrapper.scala index 821a04865a..13a39a259d 100644 --- a/tests/src/test/scala/cats/tests/ListWrapper.scala +++ b/tests/src/test/scala/cats/tests/ListWrapper.scala @@ -1,7 +1,6 @@ package cats package tests -import cats.Invariant import cats.instances.list._ import org.scalacheck.{Arbitrary, Cogen} import org.scalacheck.Arbitrary.arbitrary @@ -43,10 +42,10 @@ object ListWrapper { def eqv[A : Eq]: Eq[ListWrapper[A]] = Eq.by(_.list) - val traverse: Traverse[ListWrapper] = { + val traverse: Traverse[ListWrapper] with InvariantSemigroupal[ListWrapper] = { val F = Traverse[List] - new Traverse[ListWrapper] { + new Traverse[ListWrapper] with InvariantSemigroupal[ListWrapper] { def foldLeft[A, B](fa: ListWrapper[A], b: B)(f: (B, A) => B): B = F.foldLeft(fa.list, b)(f) def foldRight[A, B](fa: ListWrapper[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = @@ -54,6 +53,8 @@ object ListWrapper { def traverse[G[_], A, B](fa: ListWrapper[A])(f: A => G[B])(implicit G0: Applicative[G]): G[ListWrapper[B]] = { G0.map(F.traverse(fa.list)(f))(ListWrapper.apply) } + def product[A, B](fa: ListWrapper[A], fb: ListWrapper[B]): ListWrapper[(A, B)] = + ListWrapper(fa.list.flatMap(a => fb.list.map(b => (a, b)))) } } @@ -61,7 +62,7 @@ object ListWrapper { val functor: Functor[ListWrapper] = traverse - val invariant: Invariant[ListWrapper] = functor + val invariant: InvariantSemigroupal[ListWrapper] = traverse val semigroupK: SemigroupK[ListWrapper] = new SemigroupK[ListWrapper] { diff --git a/tests/src/test/scala/cats/tests/MonoidSuite.scala b/tests/src/test/scala/cats/tests/MonoidSuite.scala index b96a146418..a05b0c1c86 100644 --- a/tests/src/test/scala/cats/tests/MonoidSuite.scala +++ b/tests/src/test/scala/cats/tests/MonoidSuite.scala @@ -6,7 +6,7 @@ package tests class MonoidSuite extends CatsSuite { { Invariant[Monoid] - Semigroupal[Monoid] + InvariantSemigroupal[Monoid] } test("companion object syntax") { @@ -19,7 +19,7 @@ class MonoidSuite extends CatsSuite { object MonoidSuite { def summonInstance(): Unit = { Invariant[Monoid] - Semigroupal[Monoid] + InvariantSemigroupal[Monoid] () } diff --git a/tests/src/test/scala/cats/tests/NestedSuite.scala b/tests/src/test/scala/cats/tests/NestedSuite.scala index d7149e64d0..a5b25f0242 100644 --- a/tests/src/test/scala/cats/tests/NestedSuite.scala +++ b/tests/src/test/scala/cats/tests/NestedSuite.scala @@ -50,6 +50,15 @@ class NestedSuite extends CatsSuite { checkAll("Contravariant[Nested[Option, Show, ?]]", SerializableTests.serializable(Contravariant[Nested[Option, Show, ?]])) } + { + // InvariantSemigroupal + Apply functor composition + implicit val instance = ListWrapper.invariant + checkAll("Nested[ListWrapper, Option, ?]", + InvariantSemigroupalTests[Nested[ListWrapper, Option, ?]].invariantSemigroupal[Int, Int, Int]) + checkAll("InvariantSemigroupal[Nested[ListWrapper, Const[String, ?], ?]", + SerializableTests.serializable(InvariantSemigroupal[Nested[ListWrapper, Option, ?]])) + } + { // Applicative + ContravariantMonoidal functor composition checkAll("Nested[Option, Const[String, ?], ?]", From 38b46e641cb0d1d39f822ca9467e9f4ccfb27ec8 Mon Sep 17 00:00:00 2001 From: Luka Jacobowitz Date: Tue, 12 Dec 2017 14:23:57 +0100 Subject: [PATCH 06/18] Remodel hierarchy --- build.sbt | 1 + core/src/main/scala/cats/Applicative.scala | 14 +------------- core/src/main/scala/cats/Apply.scala | 2 +- .../main/scala/cats/ContravariantMonoidal.scala | 4 +++- .../main/scala/cats/ContravariantSemigroupal.scala | 2 +- core/src/main/scala/cats/InvariantMonoidal.scala | 11 +++++++++++ 6 files changed, 18 insertions(+), 16 deletions(-) diff --git a/build.sbt b/build.sbt index 781310b18d..1189c582e4 100644 --- a/build.sbt +++ b/build.sbt @@ -323,6 +323,7 @@ def mimaSettings(moduleName: String) = Seq( exclude[ReversedMissingMethodProblem]("cats.MonadError.rethrow"), exclude[ReversedMissingMethodProblem]("cats.syntax.MonadErrorSyntax.catsSyntaxMonadErrorRethrow"), exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.composeApply"), + exclude[DirectMissingMethodProblem]("cats.Semigroupal.catsSemigroupalForMonoid"), exclude[DirectMissingMethodProblem]("cats.data.CokleisliArrow.id"), exclude[IncompatibleResultTypeProblem]("cats.data.CokleisliArrow.id") ) diff --git a/core/src/main/scala/cats/Applicative.scala b/core/src/main/scala/cats/Applicative.scala index 4d54a9b7b2..44c86e8445 100644 --- a/core/src/main/scala/cats/Applicative.scala +++ b/core/src/main/scala/cats/Applicative.scala @@ -13,20 +13,8 @@ import simulacrum.typeclass * * Must obey the laws defined in cats.laws.ApplicativeLaws. */ -@typeclass trait Applicative[F[_]] extends Apply[F] { self => +@typeclass trait Applicative[F[_]] extends Apply[F] with InvariantMonoidal[F] { self => - /** - * `pure` lifts any value into the Applicative Functor. - * - * Example: - * {{{ - * scala> import cats.implicits._ - * - * scala> Applicative[Option].pure(10) - * res0: Option[Int] = Some(10) - * }}} - */ - def pure[A](x: A): F[A] /** * Returns an `F[Unit]` value, equivalent with `pure(())`. diff --git a/core/src/main/scala/cats/Apply.scala b/core/src/main/scala/cats/Apply.scala index a91a1086f4..01f5087e56 100644 --- a/core/src/main/scala/cats/Apply.scala +++ b/core/src/main/scala/cats/Apply.scala @@ -8,7 +8,7 @@ import simulacrum.typeclass * Must obey the laws defined in cats.laws.ApplyLaws. */ @typeclass(excludeParents = List("ApplyArityFunctions")) -trait Apply[F[_]] extends Functor[F] with Semigroupal[F] with ApplyArityFunctions[F] { self => +trait Apply[F[_]] extends Functor[F] with InvariantSemigroupal[F] with ApplyArityFunctions[F] { self => /** * Given a value and a function in the Apply context, applies the diff --git a/core/src/main/scala/cats/ContravariantMonoidal.scala b/core/src/main/scala/cats/ContravariantMonoidal.scala index ec273deb7c..8bfa044d87 100644 --- a/core/src/main/scala/cats/ContravariantMonoidal.scala +++ b/core/src/main/scala/cats/ContravariantMonoidal.scala @@ -11,13 +11,15 @@ import simulacrum.typeclass * Based on ekmett's contravariant library: * https://hackage.haskell.org/package/contravariant-1.4/docs/Data-Functor-Contravariant-Divisible.html */ -@typeclass trait ContravariantMonoidal[F[_]] extends ContravariantSemigroupal[F] { self => +@typeclass trait ContravariantMonoidal[F[_]] extends ContravariantSemigroupal[F] with InvariantMonoidal[F] { /** * `unit` produces an instance of `F` for any type `A` * that is trivial with respect to `contramap2` along * the diagonal */ def unit[A]: F[A] + + override def pure[A](a: A): F[A] = unit } object ContravariantMonoidal extends SemigroupalArityFunctions { def monoid[F[_], A](implicit f: ContravariantMonoidal[F], monoid: Monoid[A]): Monoid[F[A]] = diff --git a/core/src/main/scala/cats/ContravariantSemigroupal.scala b/core/src/main/scala/cats/ContravariantSemigroupal.scala index 7a41095334..8a451db557 100644 --- a/core/src/main/scala/cats/ContravariantSemigroupal.scala +++ b/core/src/main/scala/cats/ContravariantSemigroupal.scala @@ -6,7 +6,7 @@ import simulacrum.typeclass * [[ContravariantSemigroupal]] is nothing more than something both contravariant * and Semigroupal. It comes up enough to be useful, and composes well */ -@typeclass trait ContravariantSemigroupal[F[_]] extends Semigroupal[F] with Contravariant[F] { self => +@typeclass trait ContravariantSemigroupal[F[_]] extends InvariantSemigroupal[F] with Contravariant[F] { self => override def composeFunctor[G[_]: Functor]: ContravariantSemigroupal[λ[α => F[G[α]]]] = new ComposedSemigroupal[F, G] { def F = self diff --git a/core/src/main/scala/cats/InvariantMonoidal.scala b/core/src/main/scala/cats/InvariantMonoidal.scala index 08381b1ec9..67f48683a2 100644 --- a/core/src/main/scala/cats/InvariantMonoidal.scala +++ b/core/src/main/scala/cats/InvariantMonoidal.scala @@ -8,6 +8,17 @@ import simulacrum.typeclass * Must obey the laws defined in cats.laws.InvariantMonoidalLaws. */ @typeclass trait InvariantMonoidal[F[_]] extends InvariantSemigroupal[F] { + /** + * `pure` lifts any value into a Monoidal Functor. + * + * Example: + * {{{ + * scala> import cats.implicits._ + * + * scala> InvariantMonoidal[Option].pure(10) + * res0: Option[Int] = Some(10) + * }}} + */ def pure[A](a: A): F[A] } From f4b7490e47bcb36224c34eee64a95a20d670e777 Mon Sep 17 00:00:00 2001 From: Luka Jacobowitz Date: Tue, 12 Dec 2017 16:01:49 +0100 Subject: [PATCH 07/18] Move monoid and semigroup functions to the instance --- build.sbt | 93 +++++++++++++++++++ core/src/main/scala/cats/Applicative.scala | 3 + core/src/main/scala/cats/Apply.scala | 5 +- .../scala/cats/ContravariantMonoidal.scala | 2 +- .../scala/cats/ContravariantSemigroupal.scala | 3 + .../main/scala/cats/InvariantMonoidal.scala | 11 ++- .../scala/cats/InvariantSemigroupal.scala | 23 ++--- .../main/scala/cats/instances/invariant.scala | 15 ++- .../CsvCodecInvariantMonoidalSuite.scala | 2 +- .../test/scala/cats/tests/MonoidSuite.scala | 1 - 10 files changed, 132 insertions(+), 26 deletions(-) diff --git a/build.sbt b/build.sbt index 1189c582e4..c521140994 100644 --- a/build.sbt +++ b/build.sbt @@ -324,6 +324,99 @@ def mimaSettings(moduleName: String) = Seq( exclude[ReversedMissingMethodProblem]("cats.syntax.MonadErrorSyntax.catsSyntaxMonadErrorRethrow"), exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.composeApply"), exclude[DirectMissingMethodProblem]("cats.Semigroupal.catsSemigroupalForMonoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[ReversedMissingMethodProblem]("cats.ContravariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[ReversedMissingMethodProblem]("cats.Applicative.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[ReversedMissingMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[ReversedMissingMethodProblem]("cats.Apply.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), + exclude[ReversedMissingMethodProblem]("cats.instances.InvariantMonoidalInstances.catsSemigroupalForMonoid"), exclude[DirectMissingMethodProblem]("cats.data.CokleisliArrow.id"), exclude[IncompatibleResultTypeProblem]("cats.data.CokleisliArrow.id") ) diff --git a/core/src/main/scala/cats/Applicative.scala b/core/src/main/scala/cats/Applicative.scala index 44c86e8445..a8d8e06c04 100644 --- a/core/src/main/scala/cats/Applicative.scala +++ b/core/src/main/scala/cats/Applicative.scala @@ -171,6 +171,9 @@ import simulacrum.typeclass */ def whenA[A](cond: Boolean)(f: => F[A]): F[Unit] = if (cond) void(f) else pure(()) + + override def monoid[A](implicit A: Monoid[A]): Monoid[F[A]] = + new ApplicativeMonoid[F, A](this, A) } object Applicative { diff --git a/core/src/main/scala/cats/Apply.scala b/core/src/main/scala/cats/Apply.scala index 01f5087e56..7846e5b64e 100644 --- a/core/src/main/scala/cats/Apply.scala +++ b/core/src/main/scala/cats/Apply.scala @@ -79,11 +79,14 @@ trait Apply[F[_]] extends Functor[F] with InvariantSemigroupal[F] with ApplyArit val F = self val G = Apply[G] } + + override def semigroup[A](implicit A: Semigroup[A]): Semigroup[F[A]] = + new ApplySemigroup[F, A](this, A) } object Apply { def semigroup[F[_], A](implicit f: Apply[F], sg: Semigroup[A]): Semigroup[F[A]] = - new ApplySemigroup[F, A](f, sg) + f.semigroup } private[cats] class ApplySemigroup[F[_], A](f: Apply[F], sg: Semigroup[A]) extends Semigroup[F[A]] { diff --git a/core/src/main/scala/cats/ContravariantMonoidal.scala b/core/src/main/scala/cats/ContravariantMonoidal.scala index 8bfa044d87..3d70cf7815 100644 --- a/core/src/main/scala/cats/ContravariantMonoidal.scala +++ b/core/src/main/scala/cats/ContravariantMonoidal.scala @@ -22,7 +22,7 @@ import simulacrum.typeclass override def pure[A](a: A): F[A] = unit } object ContravariantMonoidal extends SemigroupalArityFunctions { - def monoid[F[_], A](implicit f: ContravariantMonoidal[F], monoid: Monoid[A]): Monoid[F[A]] = + def monoid[F[_], A](implicit f: ContravariantMonoidal[F]): Monoid[F[A]] = new ContravariantMonoidalMonoid[F, A](f) } diff --git a/core/src/main/scala/cats/ContravariantSemigroupal.scala b/core/src/main/scala/cats/ContravariantSemigroupal.scala index 8a451db557..8773550ad5 100644 --- a/core/src/main/scala/cats/ContravariantSemigroupal.scala +++ b/core/src/main/scala/cats/ContravariantSemigroupal.scala @@ -12,6 +12,9 @@ import simulacrum.typeclass def F = self def G = Functor[G] } + + override def semigroup[A](implicit A: Semigroup[A]): Semigroup[F[A]] = + new ContravariantSemigroupalSemigroup[F, A](this) } object ContravariantSemigroupal extends SemigroupalArityFunctions { diff --git a/core/src/main/scala/cats/InvariantMonoidal.scala b/core/src/main/scala/cats/InvariantMonoidal.scala index 67f48683a2..ed472f815a 100644 --- a/core/src/main/scala/cats/InvariantMonoidal.scala +++ b/core/src/main/scala/cats/InvariantMonoidal.scala @@ -20,13 +20,16 @@ import simulacrum.typeclass * }}} */ def pure[A](a: A): F[A] -} -object InvariantMonoidal { - def monoid[F[_], A](implicit f: InvariantMonoidal[F], monoid: Monoid[A]): Monoid[F[A]] = - new InvariantMonoidalMonoid[F, A](f, monoid) + /** + * Gives a `Monoid` instance if A itself has a `Monoid` instance. + */ + def monoid[A](implicit A: Monoid[A]): Monoid[F[A]] = + new InvariantMonoidalMonoid[F, A](this, A) + } + private[cats] class InvariantMonoidalMonoid[F[_], A](f: InvariantMonoidal[F], monoid: Monoid[A]) extends InvariantSemigroupalSemigroup(f, monoid) with Monoid[F[A]] { def empty: F[A] = f.pure(monoid.empty) } diff --git a/core/src/main/scala/cats/InvariantSemigroupal.scala b/core/src/main/scala/cats/InvariantSemigroupal.scala index 9e6b59d7be..53e930358f 100644 --- a/core/src/main/scala/cats/InvariantSemigroupal.scala +++ b/core/src/main/scala/cats/InvariantSemigroupal.scala @@ -14,26 +14,15 @@ import simulacrum.typeclass def G = Apply[G] } + /** + * Gives a `Semigroup` instance if A itself has a `Semigroup` instance. + */ + def semigroup[A](implicit A: Semigroup[A]): Semigroup[F[A]] = + new InvariantSemigroupalSemigroup[F, A](this, A) } -object InvariantSemigroupal extends SemigroupalArityFunctions { - def semigroup[F[_], A](implicit f: InvariantSemigroupal[F], sg: Semigroup[A]): Semigroup[F[A]] = - new InvariantSemigroupalSemigroup[F, A](f, sg) - - implicit def catsSemigroupalForMonoid: InvariantSemigroupal[Monoid] = new InvariantSemigroupal[Monoid] { - def product[A, B](fa: Monoid[A], fb: Monoid[B]): Monoid[(A, B)] = new Monoid[(A, B)] { - val empty = fa.empty -> fb.empty - def combine(x: (A, B), y: (A, B)): (A, B) = fa.combine(x._1, y._1) -> fb.combine(x._2, y._2) - } - - def imap[A, B](fa: Monoid[A])(f: A => B)(g: B => A): Monoid[B] = new Monoid[B] { - def empty: B = f(fa.empty) - - def combine(x: B, y: B): B = f(fa.combine(g(x), g(y))) - } - } -} +object InvariantSemigroupal extends SemigroupalArityFunctions private[cats] class InvariantSemigroupalSemigroup[F[_], A](f: InvariantSemigroupal[F], sg: Semigroup[A]) extends Semigroup[F[A]] { def combine(a: F[A], b: F[A]): F[A] = diff --git a/core/src/main/scala/cats/instances/invariant.scala b/core/src/main/scala/cats/instances/invariant.scala index c2e9a968bb..3716e79dba 100644 --- a/core/src/main/scala/cats/instances/invariant.scala +++ b/core/src/main/scala/cats/instances/invariant.scala @@ -1,10 +1,23 @@ package cats.instances import cats.kernel._ -import cats.InvariantMonoidal +import cats.{InvariantMonoidal, Monoid, InvariantSemigroupal} trait InvariantMonoidalInstances { + implicit def catsSemigroupalForMonoid: InvariantSemigroupal[Monoid] = new InvariantSemigroupal[Monoid] { + def product[A, B](fa: Monoid[A], fb: Monoid[B]): Monoid[(A, B)] = new Monoid[(A, B)] { + val empty = fa.empty -> fb.empty + def combine(x: (A, B), y: (A, B)): (A, B) = fa.combine(x._1, y._1) -> fb.combine(x._2, y._2) + } + + def imap[A, B](fa: Monoid[A])(f: A => B)(g: B => A): Monoid[B] = new Monoid[B] { + def empty: B = f(fa.empty) + + def combine(x: B, y: B): B = f(fa.combine(g(x), g(y))) + } + } + implicit val catsInvariantMonoidalSemigroup: InvariantMonoidal[Semigroup] = new InvariantMonoidal[Semigroup] { def product[A, B](fa: Semigroup[A], fb: Semigroup[B]): Semigroup[(A, B)] = new Semigroup[(A, B)] { def combine(x: (A, B), y: (A, B)): (A, B) = fa.combine(x._1, y._1) -> fb.combine(x._2, y._2) diff --git a/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala b/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala index 2957f9c071..80eab16119 100644 --- a/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala +++ b/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala @@ -95,7 +95,7 @@ class CsvCodecInvariantMonoidalSuite extends CatsSuite { checkAll("InvariantMonoidal[CsvCodec]", SerializableTests.serializable(InvariantMonoidal[CsvCodec])) { - implicit val csvMonoid = InvariantMonoidal.monoid[CsvCodec, Int] + implicit val csvMonoid = InvariantMonoidal[CsvCodec].monoid[Int] checkAll("InvariantMonoidal[CsvCodec].monoid", MonoidTests[CsvCodec[Int]].monoid) } } diff --git a/tests/src/test/scala/cats/tests/MonoidSuite.scala b/tests/src/test/scala/cats/tests/MonoidSuite.scala index a05b0c1c86..702297b92c 100644 --- a/tests/src/test/scala/cats/tests/MonoidSuite.scala +++ b/tests/src/test/scala/cats/tests/MonoidSuite.scala @@ -19,7 +19,6 @@ class MonoidSuite extends CatsSuite { object MonoidSuite { def summonInstance(): Unit = { Invariant[Monoid] - InvariantSemigroupal[Monoid] () } From f9df1c3af18ba2659ae09d3b4c8d0708a42dd68b Mon Sep 17 00:00:00 2001 From: Luka Jacobowitz Date: Tue, 12 Dec 2017 18:47:02 +0100 Subject: [PATCH 08/18] More Tests --- core/src/main/scala/cats/Applicative.scala | 2 +- .../test/scala/cats/tests/ApplicativeSuite.scala | 13 +++++++++++++ .../test/scala/cats/tests/ContravariantSuite.scala | 6 +++++- .../cats/tests/CsvCodecInvariantMonoidalSuite.scala | 7 ++++++- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/core/src/main/scala/cats/Applicative.scala b/core/src/main/scala/cats/Applicative.scala index a8d8e06c04..09cb6e4f4a 100644 --- a/core/src/main/scala/cats/Applicative.scala +++ b/core/src/main/scala/cats/Applicative.scala @@ -178,7 +178,7 @@ import simulacrum.typeclass object Applicative { def monoid[F[_], A](implicit f: Applicative[F], monoid: Monoid[A]): Monoid[F[A]] = - new ApplicativeMonoid[F, A](f, monoid) + f.monoid } private[cats] class ApplicativeMonoid[F[_], A](f: Applicative[F], monoid: Monoid[A]) extends ApplySemigroup(f, monoid) with Monoid[F[A]] { diff --git a/tests/src/test/scala/cats/tests/ApplicativeSuite.scala b/tests/src/test/scala/cats/tests/ApplicativeSuite.scala index 11b0f0cce0..01b8be94cb 100644 --- a/tests/src/test/scala/cats/tests/ApplicativeSuite.scala +++ b/tests/src/test/scala/cats/tests/ApplicativeSuite.scala @@ -2,6 +2,7 @@ package cats package tests import cats.Applicative +import cats.kernel.laws.discipline.{MonoidTests, SemigroupTests} class ApplicativeSuite extends CatsSuite { @@ -36,4 +37,16 @@ class ApplicativeSuite extends CatsSuite { } } + { + implicit val listwrapperApplicative = ListWrapper.applicative + implicit val listwrapperMonoid = Applicative.monoid[ListWrapper, Int] + checkAll("Applicative[ListWrapper].monoid", MonoidTests[ListWrapper[Int]].monoid) + } + + { + implicit val listwrapperApplicative = ListWrapper.applyInstance + implicit val listwrapperSemigroup = Apply.semigroup[ListWrapper, Int] + checkAll("Apply[ListWrapper].semigroup", SemigroupTests[ListWrapper[Int]].semigroup) + } + } diff --git a/tests/src/test/scala/cats/tests/ContravariantSuite.scala b/tests/src/test/scala/cats/tests/ContravariantSuite.scala index e18add48fd..e156c69719 100644 --- a/tests/src/test/scala/cats/tests/ContravariantSuite.scala +++ b/tests/src/test/scala/cats/tests/ContravariantSuite.scala @@ -2,7 +2,7 @@ package cats package tests import cats.data.Const -import cats.kernel.laws.discipline.MonoidTests +import cats.kernel.laws.discipline.{MonoidTests, SemigroupTests} import cats.laws.discipline.ContravariantMonoidalTests import org.scalactic.CanEqual import org.scalacheck.{Arbitrary, Cogen} @@ -46,5 +46,9 @@ class ContravariantSuite extends CatsSuite { implicit val predicateMonoid = ContravariantMonoidal.monoid[Predicate, Int] checkAll("ContravariantMonoidal[Predicate].monoid", MonoidTests[Predicate[Int]].monoid) } + { + implicit val predicateSemigroup = ContravariantSemigroupal.semigroup[Predicate, Int] + checkAll("ContravariantSemigroupal[Predicate].semigroup", SemigroupTests[Predicate[Int]].semigroup) + } } diff --git a/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala b/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala index 80eab16119..43c3c1c3b4 100644 --- a/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala +++ b/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala @@ -6,7 +6,7 @@ import cats.laws.discipline.{InvariantMonoidalTests, SerializableTests} import cats.instances.all._ import cats.syntax.apply._ import cats.Eq -import cats.kernel.laws.discipline.MonoidTests +import cats.kernel.laws.discipline.{MonoidTests, SemigroupTests} import org.scalacheck.{Arbitrary, Gen} object CsvCodecInvariantMonoidalSuite { @@ -98,4 +98,9 @@ class CsvCodecInvariantMonoidalSuite extends CatsSuite { implicit val csvMonoid = InvariantMonoidal[CsvCodec].monoid[Int] checkAll("InvariantMonoidal[CsvCodec].monoid", MonoidTests[CsvCodec[Int]].monoid) } + + { + implicit val csvSemigroup = InvariantSemigroupal[CsvCodec].semigroup[Int] + checkAll("InvariantSemigroupal[CsvCodec].semigroup", SemigroupTests[CsvCodec[Int]].semigroup) + } } From 8e2f7abab233be77ca2624910cc851e2b6f85249 Mon Sep 17 00:00:00 2001 From: Luka Jacobowitz Date: Wed, 13 Dec 2017 23:56:18 +0000 Subject: [PATCH 09/18] Use def unit: F[Unit] as base for Monoidal --- core/src/main/scala/cats/Applicative.scala | 15 ++++++++++++++ core/src/main/scala/cats/Composed.scala | 2 +- .../scala/cats/ContravariantMonoidal.scala | 8 +++----- .../main/scala/cats/InvariantMonoidal.scala | 10 ++++++---- core/src/main/scala/cats/data/Const.scala | 4 ++-- core/src/main/scala/cats/data/IdT.scala | 2 +- .../main/scala/cats/data/IndexedStateT.scala | 6 +++--- core/src/main/scala/cats/data/Kleisli.scala | 2 +- core/src/main/scala/cats/data/Nested.scala | 2 +- core/src/main/scala/cats/data/OptionT.scala | 2 +- core/src/main/scala/cats/data/Tuple2K.scala | 2 +- core/src/main/scala/cats/data/WriterT.scala | 2 +- core/src/main/scala/cats/instances/eq.scala | 2 +- .../src/main/scala/cats/instances/equiv.scala | 4 ++-- .../main/scala/cats/instances/function.scala | 2 +- .../main/scala/cats/instances/invariant.scala | 20 ++++--------------- .../src/main/scala/cats/instances/order.scala | 2 +- .../main/scala/cats/instances/ordering.scala | 4 ++-- .../cats/laws/ContravariantMonoidalLaws.scala | 8 ++++---- .../cats/laws/InvariantMonoidalLaws.scala | 4 ++-- .../cats/tests/AlgebraInvariantSuite.scala | 4 ++-- .../scala/cats/tests/ContravariantSuite.scala | 2 +- .../CsvCodecInvariantMonoidalSuite.scala | 6 +++--- 23 files changed, 59 insertions(+), 56 deletions(-) diff --git a/core/src/main/scala/cats/Applicative.scala b/core/src/main/scala/cats/Applicative.scala index 83dcf7ac3e..ebc9788114 100644 --- a/core/src/main/scala/cats/Applicative.scala +++ b/core/src/main/scala/cats/Applicative.scala @@ -17,6 +17,21 @@ import simulacrum.typeclass @typeclass trait Applicative[F[_]] extends Apply[F] with InvariantMonoidal[F] { self => + + /** + * `pure` lifts any value into the Applicative Functor. + * + * Example: + * {{{ + * scala> import cats.implicits._ + * + * scala> Applicative[Option].pure(10) + * res0: Option[Int] = Some(10) + * }}} + */ + def pure[A](x: A): F[A] + + /** * Returns an `F[Unit]` value, equivalent with `pure(())`. * diff --git a/core/src/main/scala/cats/Composed.scala b/core/src/main/scala/cats/Composed.scala index 3d445c020e..c1ba6b9f5c 100644 --- a/core/src/main/scala/cats/Composed.scala +++ b/core/src/main/scala/cats/Composed.scala @@ -117,7 +117,7 @@ private[cats] trait ComposedApplicativeContravariantMonoidal[F[_], G[_]] extends def F: Applicative[F] def G: ContravariantMonoidal[G] - override def unit[A]: F[G[A]] = F.pure(G.unit) + override def unit: F[G[Unit]] = F.pure(G.unit) override def contramap[A, B](fa: F[G[A]])(f: B => A): F[G[B]] = F.map(fa)(G.contramap(_)(f)) diff --git a/core/src/main/scala/cats/ContravariantMonoidal.scala b/core/src/main/scala/cats/ContravariantMonoidal.scala index 29f8a0a4ed..45e4d95c5f 100644 --- a/core/src/main/scala/cats/ContravariantMonoidal.scala +++ b/core/src/main/scala/cats/ContravariantMonoidal.scala @@ -13,13 +13,11 @@ import simulacrum.typeclass */ @typeclass trait ContravariantMonoidal[F[_]] extends ContravariantSemigroupal[F] with InvariantMonoidal[F] { /** - * `unit` produces an instance of `F` for any type `A` + * `conquer` produces an instance of `F` for any type `A` * that is trivial with respect to `contramap2` along * the diagonal */ - def unit[A]: F[A] - - override def pure[A](a: A): F[A] = unit + def conquer[A]: F[A] = contramap(unit)(_ => ()) override def monoid[A](implicit A: Monoid[A]): Monoid[F[A]] = ContravariantMonoidal.monoid(this) @@ -30,5 +28,5 @@ object ContravariantMonoidal extends SemigroupalArityFunctions { } private[cats] class ContravariantMonoidalMonoid[F[_], A](f: ContravariantMonoidal[F]) extends ContravariantSemigroupalSemigroup[F, A](f) with Monoid[F[A]] { - def empty: F[A] = f.unit + def empty: F[A] = f.conquer } diff --git a/core/src/main/scala/cats/InvariantMonoidal.scala b/core/src/main/scala/cats/InvariantMonoidal.scala index ed472f815a..61b6a827d3 100644 --- a/core/src/main/scala/cats/InvariantMonoidal.scala +++ b/core/src/main/scala/cats/InvariantMonoidal.scala @@ -9,17 +9,19 @@ import simulacrum.typeclass */ @typeclass trait InvariantMonoidal[F[_]] extends InvariantSemigroupal[F] { /** - * `pure` lifts any value into a Monoidal Functor. + * `point` lifts any value into a Monoidal Functor. * * Example: * {{{ * scala> import cats.implicits._ * - * scala> InvariantMonoidal[Option].pure(10) + * scala> InvariantMonoidal[Option].point(10) * res0: Option[Int] = Some(10) * }}} */ - def pure[A](a: A): F[A] + def point[A](a: A): F[A] = imap(unit)(_ => a)(_ => ()) + + def unit: F[Unit] /** * Gives a `Monoid` instance if A itself has a `Monoid` instance. @@ -31,5 +33,5 @@ import simulacrum.typeclass private[cats] class InvariantMonoidalMonoid[F[_], A](f: InvariantMonoidal[F], monoid: Monoid[A]) extends InvariantSemigroupalSemigroup(f, monoid) with Monoid[F[A]] { - def empty: F[A] = f.pure(monoid.empty) + def empty: F[A] = f.point(monoid.empty) } diff --git a/core/src/main/scala/cats/data/Const.scala b/core/src/main/scala/cats/data/Const.scala index b076870bdf..97c5b033d9 100644 --- a/core/src/main/scala/cats/data/Const.scala +++ b/core/src/main/scala/cats/data/Const.scala @@ -66,7 +66,7 @@ private[data] sealed abstract class ConstInstances extends ConstInstances0 { } implicit def catsDataContravariantMonoidalForConst[D: Monoid]: ContravariantMonoidal[Const[D, ?]] = new ContravariantMonoidal[Const[D, ?]] { - override def unit[A] = Const.empty[D, A] + override def unit = Const.empty[D, Unit] override def contramap[A, B](fa: Const[D, A])(f: B => A): Const[D, B] = fa.retag[B] override def product[A, B](fa: Const[D, A], fb: Const[D, B]): Const[D, (A, B)] = @@ -136,7 +136,7 @@ private[data] sealed abstract class ConstInstances0 extends ConstInstances1 { private[data] sealed abstract class ConstInstances1 { implicit def catsConstInvariantMonoidal[C: Monoid]: InvariantMonoidal[Const[C, ?]] = new InvariantMonoidal[Const[C, ?]] { - def pure[A](a: A): Const[C, A] = + def unit: Const[C, Unit] = Const.empty def imap[A, B](fa: Const[C, A])(f: A => B)(g: B => A): Const[C, B] = diff --git a/core/src/main/scala/cats/data/IdT.scala b/core/src/main/scala/cats/data/IdT.scala index 7a79b014dc..c8faf45771 100644 --- a/core/src/main/scala/cats/data/IdT.scala +++ b/core/src/main/scala/cats/data/IdT.scala @@ -76,7 +76,7 @@ private[data] sealed trait IdTApplicative[F[_]] extends Applicative[IdT[F, ?]] w private[data] sealed trait IdTContravariantMonoidal[F[_]] extends ContravariantMonoidal[IdT[F, ?]] { implicit val F0: ContravariantMonoidal[F] - override def unit[A]: IdT[F, A] = IdT(F0.unit[A]) + override def unit: IdT[F, Unit] = IdT(F0.unit) override def contramap[A, B](fa: IdT[F, A])(f: B => A): IdT[F, B] = IdT(F0.contramap(fa.value)(f)) diff --git a/core/src/main/scala/cats/data/IndexedStateT.scala b/core/src/main/scala/cats/data/IndexedStateT.scala index 06016b1ee7..9718d0b19d 100644 --- a/core/src/main/scala/cats/data/IndexedStateT.scala +++ b/core/src/main/scala/cats/data/IndexedStateT.scala @@ -387,11 +387,11 @@ private[data] sealed abstract class IndexedStateTContravariantMonoidal[F[_], S] implicit def F: ContravariantMonoidal[F] implicit def G: Applicative[F] - override def unit[A]: IndexedStateT[F, S, S, A] = - IndexedStateT.applyF(G.pure((s: S) => F.unit[(S, A)])) + override def unit: IndexedStateT[F, S, S, Unit] = + IndexedStateT.applyF(G.pure((s: S) => F.conquer[(S, Unit)])) override def contramap[A, B](fa: IndexedStateT[F, S, S, A])(f: B => A): IndexedStateT[F, S, S, B] = - contramap2(fa, unit)(((a: A) => (a, a)) compose f) + contramap2(fa, conquer)(((a: A) => (a, a)) compose f) override def product[A, B](fa: IndexedStateT[F, S, S, A], fb: IndexedStateT[F, S, S, B]): IndexedStateT[F, S, S, (A, B)] = contramap2(fa, fb)(identity) diff --git a/core/src/main/scala/cats/data/Kleisli.scala b/core/src/main/scala/cats/data/Kleisli.scala index 5e86a0cf59..2c6c7d5761 100644 --- a/core/src/main/scala/cats/data/Kleisli.scala +++ b/core/src/main/scala/cats/data/Kleisli.scala @@ -317,7 +317,7 @@ private[data] trait KleisliAlternative[F[_], A] extends Alternative[Kleisli[F, A private[data] sealed trait KleisliContravariantMonoidal[F[_], D] extends ContravariantMonoidal[Kleisli[F, D, ?]] { implicit def F: ContravariantMonoidal[F] - override def unit[A]: Kleisli[F, D, A] = Kleisli(Function.const(F.unit[A])) + override def unit: Kleisli[F, D, Unit] = Kleisli(Function.const(F.unit)) override def contramap[A, B](fa: Kleisli[F, D, A])(f: B => A): Kleisli[F, D, B] = Kleisli(d => F.contramap(fa.run(d))(f)) diff --git a/core/src/main/scala/cats/data/Nested.scala b/core/src/main/scala/cats/data/Nested.scala index 1538a527d2..b5dd11be87 100644 --- a/core/src/main/scala/cats/data/Nested.scala +++ b/core/src/main/scala/cats/data/Nested.scala @@ -279,7 +279,7 @@ private[data] trait NestedContravariant[F[_], G[_]] extends Contravariant[Nested private[data] trait NestedContravariantMonoidal[F[_], G[_]] extends ContravariantMonoidal[Nested[F, G, ?]] { def FG: ContravariantMonoidal[λ[α => F[G[α]]]] - def unit[A]: Nested[F, G, A] = Nested(FG.unit) + def unit: Nested[F, G, Unit] = Nested(FG.unit) def contramap[A, B](fa: Nested[F, G, A])(f: B => A): Nested[F, G, B] = Nested(FG.contramap(fa.value)(f)) diff --git a/core/src/main/scala/cats/data/OptionT.scala b/core/src/main/scala/cats/data/OptionT.scala index df24420c1b..64d213ab4b 100644 --- a/core/src/main/scala/cats/data/OptionT.scala +++ b/core/src/main/scala/cats/data/OptionT.scala @@ -300,7 +300,7 @@ private trait OptionTMonadError[F[_], E] extends MonadError[OptionT[F, ?], E] wi private trait OptionTContravariantMonoidal[F[_]] extends ContravariantMonoidal[OptionT[F, ?]] { def F: ContravariantMonoidal[F] - override def unit[A]: OptionT[F, A] = OptionT (F.unit) + override def unit: OptionT[F, Unit] = OptionT(F.conquer) override def contramap[A, B](fa: OptionT[F, A])(f: B => A): OptionT[F, B] = OptionT(F.contramap(fa.value)(_ map f)) diff --git a/core/src/main/scala/cats/data/Tuple2K.scala b/core/src/main/scala/cats/data/Tuple2K.scala index dbed5a0283..2d807f2e17 100644 --- a/core/src/main/scala/cats/data/Tuple2K.scala +++ b/core/src/main/scala/cats/data/Tuple2K.scala @@ -131,7 +131,7 @@ private[data] sealed trait Tuple2KContravariant[F[_], G[_]] extends Contravarian private[data] sealed trait Tuple2KContravariantMonoidal[F[_], G[_]] extends ContravariantMonoidal[λ[α => Tuple2K[F, G, α]]] { def F: ContravariantMonoidal[F] def G: ContravariantMonoidal[G] - def unit[A]: Tuple2K[F, G, A] = Tuple2K(F.unit, G.unit) + def unit: Tuple2K[F, G, Unit] = Tuple2K(F.unit, G.unit) def product[A, B](fa: Tuple2K[F, G, A], fb: Tuple2K[F, G, B]): Tuple2K[F, G, (A, B)] = Tuple2K(F.product(fa.first, fb.first), G.product(fa.second, fb.second)) def contramap[A, B](fa: Tuple2K[F, G, A])(f: B => A): Tuple2K[F, G, B] = diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index 9cea6ae8a4..95ad8a7eed 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -378,7 +378,7 @@ private[data] sealed trait WriterTAlternative[F[_], L] extends Alternative[Write private[data] sealed trait WriterTContravariantMonoidal[F[_], L] extends ContravariantMonoidal[WriterT[F, L, ?]] { implicit def F0: ContravariantMonoidal[F] - override def unit[A]: WriterT[F, L, A] = WriterT(F0.unit[(L, A)]) + override def unit: WriterT[F, L, Unit] = WriterT(F0.conquer[(L, Unit)]) override def contramap[A, B](fa: WriterT[F, L, A])(f: B => A): WriterT[F, L, B] = WriterT(F0.contramap(fa.run)((d: (L, B)) => (d._1, f(d._2)))) diff --git a/core/src/main/scala/cats/instances/eq.scala b/core/src/main/scala/cats/instances/eq.scala index dc304686d5..d158efddbc 100644 --- a/core/src/main/scala/cats/instances/eq.scala +++ b/core/src/main/scala/cats/instances/eq.scala @@ -8,7 +8,7 @@ trait EqInstances { * Defaults to the trivial equivalence relation * contracting the type to a point */ - def unit[A]: Eq[A] = Eq.allEqual + def unit: Eq[Unit] = Eq.allEqual /** Derive an `Eq` for `B` given an `Eq[A]` and a function `B => A`. * diff --git a/core/src/main/scala/cats/instances/equiv.scala b/core/src/main/scala/cats/instances/equiv.scala index 012d189ff7..6ae653cf98 100644 --- a/core/src/main/scala/cats/instances/equiv.scala +++ b/core/src/main/scala/cats/instances/equiv.scala @@ -8,8 +8,8 @@ trait EquivInstances { * Defaults to trivially contracting the type * to a point */ - def unit[A]: Equiv[A] = new Equiv[A] { - def equiv(x: A, y: A): Boolean = true + def unit: Equiv[Unit] = new Equiv[Unit] { + def equiv(x: Unit, y: Unit): Boolean = true } /** Derive an `Equiv` for `B` given an `Equiv[A]` and a function `B => A`. diff --git a/core/src/main/scala/cats/instances/function.scala b/core/src/main/scala/cats/instances/function.scala index 19bbd678e9..f625dd6bff 100644 --- a/core/src/main/scala/cats/instances/function.scala +++ b/core/src/main/scala/cats/instances/function.scala @@ -38,7 +38,7 @@ private[instances] sealed trait Function0Instances { private[instances] sealed trait Function1Instances extends Function1Instances0 { implicit def catsStdContravariantMonoidalForFunction1[R: Monoid]: ContravariantMonoidal[? => R] = new ContravariantMonoidal[? => R] { - def unit[A]: A => R = Function.const(Monoid[R].empty) + def unit: Unit => R = Function.const(Monoid[R].empty) def contramap[A, B](fa: A => R)(f: B => A): B => R = fa compose f def product[A, B](fa: A => R, fb: B => R): ((A, B)) => R = diff --git a/core/src/main/scala/cats/instances/invariant.scala b/core/src/main/scala/cats/instances/invariant.scala index 3716e79dba..f8c43c4c7f 100644 --- a/core/src/main/scala/cats/instances/invariant.scala +++ b/core/src/main/scala/cats/instances/invariant.scala @@ -25,16 +25,10 @@ trait InvariantMonoidalInstances { def imap[A, B](fa: Semigroup[A])(f: A => B)(g: B => A): Semigroup[B] = new Semigroup[B] { def combine(x: B, y: B): B = f(fa.combine(g(x), g(y))) - override def combineAllOption(bs: TraversableOnce[B]): Option[B] = - fa.combineAllOption(bs.map(g)).map(f) } - def pure[A](a: A): Semigroup[A] = new Semigroup[A] { - def combine(x: A, y: A): A = a - override def combineAllOption(as: TraversableOnce[A]): Option[A] = - if (as.isEmpty) None - else if (as.size == 1) as.toList.headOption - else Some(a) + def unit: Semigroup[Unit] = new Semigroup[Unit] { + def combine(x: Unit, y: Unit): Unit = () } } @@ -45,16 +39,10 @@ trait InvariantMonoidalInstances { def imap[A, B](fa: CommutativeSemigroup[A])(f: A => B)(g: B => A): CommutativeSemigroup[B] = new CommutativeSemigroup[B] { def combine(x: B, y: B): B = f(fa.combine(g(x), g(y))) - override def combineAllOption(bs: TraversableOnce[B]): Option[B] = - fa.combineAllOption(bs.map(g)).map(f) } - def pure[A](a: A): CommutativeSemigroup[A] = new CommutativeSemigroup[A] { - def combine(x: A, y: A): A = a - override def combineAllOption(as: TraversableOnce[A]): Option[A] = - if (as.isEmpty) None - else if (as.size == 1) as.toList.headOption - else Some(a) + def unit: CommutativeSemigroup[Unit] = new CommutativeSemigroup[Unit] { + def combine(x: Unit, y: Unit): Unit = () } } diff --git a/core/src/main/scala/cats/instances/order.scala b/core/src/main/scala/cats/instances/order.scala index 8a239d264c..c3861ce1eb 100644 --- a/core/src/main/scala/cats/instances/order.scala +++ b/core/src/main/scala/cats/instances/order.scala @@ -7,7 +7,7 @@ trait OrderInstances extends cats.kernel.OrderToOrderingConversion { /** * Provides trivial order */ - def unit[A]: Order[A] = Order.from[A]((x: A, y: A) => 0) + def unit: Order[Unit] = Order.from[Unit]((x: Unit, y: Unit) => 0) /** Derive an `Order` for `B` given an `Order[A]` and a function `B => A`. * * Note: resulting instances are law-abiding only when the functions used are injective (represent a one-to-one mapping) diff --git a/core/src/main/scala/cats/instances/ordering.scala b/core/src/main/scala/cats/instances/ordering.scala index 5afd3b58e7..19d1fa0678 100644 --- a/core/src/main/scala/cats/instances/ordering.scala +++ b/core/src/main/scala/cats/instances/ordering.scala @@ -8,8 +8,8 @@ trait OrderingInstances { * Note: resulting instances are law-abiding only when the functions used are injective (represent a one-to-one mapping) */ - def unit[A]: Ordering[A] = new Ordering[A] { - def compare(l: A, r: A): Int = 0 + def unit: Ordering[Unit] = new Ordering[Unit] { + def compare(l: Unit, r: Unit): Int = 0 } def contramap[A, B](fa: Ordering[A])(f: B => A): Ordering[B] = fa.on(f) diff --git a/laws/src/main/scala/cats/laws/ContravariantMonoidalLaws.scala b/laws/src/main/scala/cats/laws/ContravariantMonoidalLaws.scala index 07a1cb24c6..ad0846fd42 100644 --- a/laws/src/main/scala/cats/laws/ContravariantMonoidalLaws.scala +++ b/laws/src/main/scala/cats/laws/ContravariantMonoidalLaws.scala @@ -12,16 +12,16 @@ trait ContravariantMonoidalLaws[F[_]] extends ContravariantSemigroupalLaws[F] { implicit override def F: ContravariantMonoidal[F] def contravariantMonoidalUnitRight[A](fa: F[A]): IsEq[F[A]] = - (fa, F.unit[A]).contramapN(delta[A]) <-> fa + (fa, F.conquer[A]).contramapN(delta[A]) <-> fa def contravariantMonoidalUnitLeft[A](fa: F[A]): IsEq[F[A]] = - (F.unit[A], fa).contramapN(delta[A]) <-> fa + (F.conquer[A], fa).contramapN(delta[A]) <-> fa def contravariantMonoidalContramap2CompatibleContramapLeft[A, B, C](fa: F[A], f: B => (A, C)): IsEq[F[B]] = - (fa, F.unit[C]).contramapN(f) <-> fa.contramap(f andThen (_._1)) + (fa, F.conquer[C]).contramapN(f) <-> fa.contramap(f andThen (_._1)) def contravariantMonoidalContramap2CompatibleContramapRight[A, B, C](fa: F[A], f: C => (B, A)): IsEq[F[C]] = - (F.unit[B], fa).contramapN(f) <-> fa.contramap(f andThen (_._2)) + (F.conquer[B], fa).contramapN(f) <-> fa.contramap(f andThen (_._2)) } object ContravariantMonoidalLaws { diff --git a/laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala b/laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala index f973ec3295..b3a65d5ce6 100644 --- a/laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala +++ b/laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala @@ -10,10 +10,10 @@ trait InvariantMonoidalLaws[F[_]] extends InvariantSemigroupalLaws[F] { import cats.syntax.invariant._ def invariantMonoidalLeftIdentity[A, B](fa: F[A], b: B): IsEq[F[A]] = - F.pure(b).product(fa).imap(_._2)(a => (b, a)) <-> fa + F.point(b).product(fa).imap(_._2)(a => (b, a)) <-> fa def invariantMonoidalRightIdentity[A, B](fa: F[A], b: B): IsEq[F[A]] = - fa.product(F.pure(b)).imap(_._1)(a => (a, b)) <-> fa + fa.product(F.point(b)).imap(_._1)(a => (a, b)) <-> fa def invariantMonoidalAssociativity[A, B, C](fa: F[A], fb: F[B], fc: F[C]): IsEq[F[(A, (B, C))]] = diff --git a/tests/src/test/scala/cats/tests/AlgebraInvariantSuite.scala b/tests/src/test/scala/cats/tests/AlgebraInvariantSuite.scala index 82faf03440..01a1ed62db 100644 --- a/tests/src/test/scala/cats/tests/AlgebraInvariantSuite.scala +++ b/tests/src/test/scala/cats/tests/AlgebraInvariantSuite.scala @@ -61,8 +61,8 @@ class AlgebraInvariantSuite extends CatsSuite { - checkAll("InvariantMonoidal[Semigroup]", SemigroupTests[Int](InvariantMonoidal[Semigroup].pure(0)).semigroup) - checkAll("InvariantMonoidal[CommutativeSemigroup]", CommutativeSemigroupTests[Int](InvariantMonoidal[CommutativeSemigroup].pure(0)).commutativeSemigroup) + checkAll("InvariantMonoidal[Semigroup]", SemigroupTests[Int](InvariantMonoidal[Semigroup].point(0)).semigroup) + checkAll("InvariantMonoidal[CommutativeSemigroup]", CommutativeSemigroupTests[Int](InvariantMonoidal[CommutativeSemigroup].point(0)).commutativeSemigroup) checkAll("InvariantSemigroupal[Monoid]", InvariantSemigroupalTests[Monoid].invariantSemigroupal[Int, Int, Int]) diff --git a/tests/src/test/scala/cats/tests/ContravariantSuite.scala b/tests/src/test/scala/cats/tests/ContravariantSuite.scala index e156c69719..3524633c45 100644 --- a/tests/src/test/scala/cats/tests/ContravariantSuite.scala +++ b/tests/src/test/scala/cats/tests/ContravariantSuite.scala @@ -26,7 +26,7 @@ class ContravariantSuite extends CatsSuite { implicit val contravariantMonoidalPredicate: ContravariantMonoidal[Predicate] = new ContravariantMonoidal[Predicate] { - def unit[A]: Predicate[A] = Predicate[A](Function.const(true)) + def unit: Predicate[Unit] = Predicate[Unit](Function.const(true)) def product[A, B](fa: Predicate[A], fb: Predicate[B]): Predicate[(A, B)] = Predicate(x => fa.run(x._1) && fb.run(x._2)) def contramap[A, B](fa: Predicate[A])(f: B => A): Predicate[B] = diff --git a/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala b/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala index 43c3c1c3b4..062c1f52cd 100644 --- a/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala +++ b/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala @@ -31,9 +31,9 @@ object CsvCodecInvariantMonoidalSuite { // In tut/invariantmonoidal.md pure, product and imap are defined in // their own trait to be introduced one by one, trait CCPure { - def pure[A](a: A): CsvCodec[A] = new CsvCodec[A] { - def read(s: CSV): (Option[A], CSV) = (Some(a), s) - def write(a: A): CSV = List.empty + def unit: CsvCodec[Unit] = new CsvCodec[Unit] { + def read(s: CSV): (Option[Unit], CSV) = (Some(()), s) + def write(a: Unit): CSV = List.empty } } From 3bfaf866c9e0b411ee7a9c088f69991d05ea78b9 Mon Sep 17 00:00:00 2001 From: Luka Jacobowitz Date: Thu, 14 Dec 2017 09:30:40 +0000 Subject: [PATCH 10/18] Fix docs and free --- .../tut/typeclasses/contravariantmonoidal.md | 4 ++-- .../main/tut/typeclasses/invariantmonoidal.md | 24 +++++++++---------- .../cats/free/FreeInvariantMonoidal.scala | 4 ++-- .../free/FreeInvariantMonoidalSuite.scala | 4 ++-- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/src/main/tut/typeclasses/contravariantmonoidal.md b/docs/src/main/tut/typeclasses/contravariantmonoidal.md index ddcd56cfa1..de5d3f5011 100644 --- a/docs/src/main/tut/typeclasses/contravariantmonoidal.md +++ b/docs/src/main/tut/typeclasses/contravariantmonoidal.md @@ -14,7 +14,7 @@ The `ContravariantMonoidal` type class is for [`Contravariant`](contravariant.ht import cats.Contravariant trait ContravariantMonoidal[F[_]] extends Contravariant[F] { - def unit[A]: F[A] + def unit: F[Unit] def product[A, B](fa: F[A], fc: F[B]): F[(A, B)] @@ -52,7 +52,7 @@ Then, we can exhibit a `ContravariantMonoidal` for `Predicate` by basing it on t ```tut:book:silent implicit val contravariantMonoidalPredicate: ContravariantMonoidal[Predicate] = new ContravariantMonoidal [Predicate] { - def unit[A]: Predicate[A] = Predicate[A](Function.const(true)) + def unit: Predicate[Unit] = Predicate[Unit](Function.const(true)) def product[A, B](fa: Predicate[A], fb: Predicate[B]): Predicate[(A, B)] = Predicate(x => fa.run(x._1) && fb.run(x._2)) diff --git a/docs/src/main/tut/typeclasses/invariantmonoidal.md b/docs/src/main/tut/typeclasses/invariantmonoidal.md index a8fdb49c4e..181f336dcc 100644 --- a/docs/src/main/tut/typeclasses/invariantmonoidal.md +++ b/docs/src/main/tut/typeclasses/invariantmonoidal.md @@ -7,11 +7,11 @@ scaladoc: "#cats.InvariantMonoidal" --- # Invariant Monoidal -`InvariantMonoidal` combines [`Invariant`](invariant.html) and [`Monoidal`](monoidal.html) with the addition of a `pure` methods, defined in isolation the `InvariantMonoidal` type class could be defined as follows: +`InvariantMonoidal` combines [`Invariant`](invariant.html) and `Semigroupal` with the addition of a `unit` methods, defined in isolation the `InvariantMonoidal` type class could be defined as follows: ```tut:silent trait InvariantMonoidal[F[_]] { - def pure[A](x: A): F[A] + def unit: F[Unit] def imap[A, B](fa: F[A])(f: A => B)(g: B => A): F[B] def product[A, B](fa: F[A], fb: F[B]): F[(A, B)] } @@ -23,16 +23,16 @@ This tutorial first shows how `Semigroup` is `InvariantMonoidal`, and how this c # `Semigroup` is `InvariantMonoidal` -As explained in the [`Invariant` tutorial](invariant.html), `Semigroup` forms an invariant functor. Indeed, given a `Semigroup[A]` and two functions `A => B` and `B => A`, one can construct a `Semigroup[B]` by transforming two values from type `B` to type `A`, combining these using the `Semigroup[A]`, and transforming the result back to type `B`. Thus to define an `InvariantMonoidal[Semigroup]` we need implementations for `pure` and `product`. +As explained in the [`Invariant` tutorial](invariant.html), `Semigroup` forms an invariant functor. Indeed, given a `Semigroup[A]` and two functions `A => B` and `B => A`, one can construct a `Semigroup[B]` by transforming two values from type `B` to type `A`, combining these using the `Semigroup[A]`, and transforming the result back to type `B`. Thus to define an `InvariantMonoidal[Semigroup]` we need implementations for `unit` and `product`. To construct a `Semigroup` from a single value, we can define a trivial `Semigroup` with a combine that always outputs the given value. A `Semigroup[(A, B)]` can be obtained from two `Semigroup`s for type `A` and `B` by deconstructing two pairs into elements of type `A` and `B`, combining these element using their respective `Semigroup`s, and reconstructing a pair from the results: ```tut:silent import cats.Semigroup -def pure[A](a: A): Semigroup[A] = - new Semigroup[A] { - def combine(x: A, y: A): A = a +def unit: Semigroup[Unit] = + new Semigroup[Unit] { + def combine(x: Unit, y: Unit): Unit = () } def product[A, B](fa: Semigroup[A], fb: Semigroup[B]): Semigroup[(A, B)] = @@ -88,10 +88,10 @@ forAll { (c: CsvCodec[A], a: A) => c.read(c.write(a)) == ((Some(a), List())) Let's now see how we could define an `InvariantMonoidal` instance for `CsvCodec`. Lifting a single value into a `CsvCodec` can be done "the trivial way" by consuming nothing from CSV and producing that value, and writing this value as the empty CSV: ```tut:silent -trait CCPure { - def pure[A](a: A): CsvCodec[A] = new CsvCodec[A] { - def read(s: CSV): (Option[A], CSV) = (Some(a), s) - def write(a: A): CSV = List.empty +trait CCUnit { + def unit: CsvCodec[Unit] = new CsvCodec[Unit] { + def read(s: CSV): (Option[Unit], CSV) = (Some(()), s) + def write(u: Unit): CSV = List.empty } } ``` @@ -137,7 +137,7 @@ Putting it all together: import cats.InvariantMonoidal implicit val csvCodecIsInvariantMonoidal: InvariantMonoidal[CsvCodec] = - new InvariantMonoidal[CsvCodec] with CCPure with CCProduct with CCImap + new InvariantMonoidal[CsvCodec] with CCUnit with CCProduct with CCImap ``` We can now define a few `CsvCodec` instances and use the methods provided by `InvariantMonoidal` to define `CsvCodec` from existing `CsvCodec`s: @@ -224,7 +224,7 @@ trait MultiInvariantImap3[F[_]] extends MultiInvariant[F] { } ``` -We can observe that `MultiInvariant` is none other than an alternative formulation for `InvariantMonoidal`. Indeed, `imap0` and `pure` have exactly the same signature, `imap1` and `imap` only differ by the order of their argument, and `imap2` can easily be defined in terms of `imap` and `product`: +We can observe that `MultiInvariant` is none other than an alternative formulation for `InvariantMonoidal`. Indeed, `imap1` and `imap` only differ by the order of their argument, and `imap2` can easily be defined in terms of `imap` and `product`: ```tut:silent trait Imap2FromImapProduct[F[_]] extends cats.InvariantMonoidal[F] { diff --git a/free/src/main/scala/cats/free/FreeInvariantMonoidal.scala b/free/src/main/scala/cats/free/FreeInvariantMonoidal.scala index d96383ee33..7407d7f750 100644 --- a/free/src/main/scala/cats/free/FreeInvariantMonoidal.scala +++ b/free/src/main/scala/cats/free/FreeInvariantMonoidal.scala @@ -43,7 +43,7 @@ object FreeInvariantMonoidal { private final case class Pure[F[_], A](a: A) extends FA[F, A] { def foldMap[G[_]](nt: FunctionK[F, G])(implicit im: InvariantMonoidal[G]): G[A] = - im.pure(a) + im.point(a) } private final case class Suspend[F[_], A](fa: F[A]) extends FA[F, A] { @@ -70,7 +70,7 @@ object FreeInvariantMonoidal { /** `FreeInvariantMonoidal[S, ?]` has a FreeInvariantMonoidal for any type constructor `S[_]`. */ implicit def catsFreeInvariantMonoidal[S[_]]: InvariantMonoidal[FA[S, ?]] = new InvariantMonoidal[FA[S, ?]] { - def pure[A](a: A): FA[S, A] = FreeInvariantMonoidal.pure(a) + def unit: FA[S, Unit] = FreeInvariantMonoidal.pure(()) def imap[A, B](fa: FA[S, A])(f: A => B)(g: B => A): FA[S, B] = fa.imap(f)(g) def product[A, B](fa: FA[S, A], fb: FA[S, B]): FA[S, (A, B)] = fa.product(fb) } diff --git a/free/src/test/scala/cats/free/FreeInvariantMonoidalSuite.scala b/free/src/test/scala/cats/free/FreeInvariantMonoidalSuite.scala index 86894e8d30..23e9dfed9b 100644 --- a/free/src/test/scala/cats/free/FreeInvariantMonoidalSuite.scala +++ b/free/src/test/scala/cats/free/FreeInvariantMonoidalSuite.scala @@ -31,7 +31,7 @@ class FreeInvariantMonoidalSuite extends CatsSuite { test("FreeInvariantMonoidal#fold") { val n = 2 val i1 = numericSystemCodec(8) - val i2 = InvariantMonoidal[CsvCodec].pure(n) + val i2 = InvariantMonoidal[CsvCodec].point(n) val iExpr = i1.product(i2.imap(_ * 2)(_ / 2)) val f1 = FreeInvariantMonoidal.lift[CsvCodec, Int](i1) @@ -44,7 +44,7 @@ class FreeInvariantMonoidalSuite extends CatsSuite { implicit val idIsInvariantMonoidal: InvariantMonoidal[Id] = new InvariantMonoidal[Id] { def product[A, B](fa: Id[A], fb: Id[B]): Id[(A, B)] = fa -> fb def imap[A, B](fa: Id[A])(f: A => B)(g: B => A): Id[B] = f(fa) - def pure[A](a: A): Id[A] = a + def unit: Id[Unit] = () } test("FreeInvariantMonoidal#compile") { From b7f36f2802aa3e43582003c865dcecc7cdfb1a60 Mon Sep 17 00:00:00 2001 From: Luka Jacobowitz Date: Thu, 14 Dec 2017 11:02:10 +0000 Subject: [PATCH 11/18] Fix duplicated mima exclusions --- build.sbt | 89 +++---------------------------------------------------- 1 file changed, 4 insertions(+), 85 deletions(-) diff --git a/build.sbt b/build.sbt index c521140994..3d9f47d083 100644 --- a/build.sbt +++ b/build.sbt @@ -327,96 +327,15 @@ def mimaSettings(moduleName: String) = Seq( exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), exclude[ReversedMissingMethodProblem]("cats.ContravariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), exclude[ReversedMissingMethodProblem]("cats.Applicative.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), exclude[ReversedMissingMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), exclude[ReversedMissingMethodProblem]("cats.Apply.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), exclude[ReversedMissingMethodProblem]("cats.instances.InvariantMonoidalInstances.catsSemigroupalForMonoid"), + exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.point"), + exclude[DirectMissingMethodProblem]("cats.InvariantMonoidal.pure"), + exclude[ReversedMissingMethodProblem]("cats.InvariantMonoidal.point"), + exclude[ReversedMissingMethodProblem]("cats.InvariantMonoidal.unit"), exclude[DirectMissingMethodProblem]("cats.data.CokleisliArrow.id"), exclude[IncompatibleResultTypeProblem]("cats.data.CokleisliArrow.id") ) From 94b0d2ed89fd9bc4cc251efca6ddd11cff1670e4 Mon Sep 17 00:00:00 2001 From: Luka Jacobowitz Date: Thu, 14 Dec 2017 12:16:04 +0000 Subject: [PATCH 12/18] Coverage --- core/src/main/scala/cats/Applicative.scala | 21 +++++++++---------- .../scala/cats/tests/ContravariantSuite.scala | 4 ++-- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/core/src/main/scala/cats/Applicative.scala b/core/src/main/scala/cats/Applicative.scala index ebc9788114..35709049fb 100644 --- a/core/src/main/scala/cats/Applicative.scala +++ b/core/src/main/scala/cats/Applicative.scala @@ -19,19 +19,18 @@ import simulacrum.typeclass /** - * `pure` lifts any value into the Applicative Functor. - * - * Example: - * {{{ - * scala> import cats.implicits._ - * - * scala> Applicative[Option].pure(10) - * res0: Option[Int] = Some(10) - * }}} - */ + * `pure` lifts any value into the Applicative Functor. + * + * Example: + * {{{ + * scala> import cats.implicits._ + * + * scala> Applicative[Option].pure(10) + * res0: Option[Int] = Some(10) + * }}} + */ def pure[A](x: A): F[A] - /** * Returns an `F[Unit]` value, equivalent with `pure(())`. * diff --git a/tests/src/test/scala/cats/tests/ContravariantSuite.scala b/tests/src/test/scala/cats/tests/ContravariantSuite.scala index 3524633c45..a70200d36a 100644 --- a/tests/src/test/scala/cats/tests/ContravariantSuite.scala +++ b/tests/src/test/scala/cats/tests/ContravariantSuite.scala @@ -43,11 +43,11 @@ class ContravariantSuite extends CatsSuite { checkAll("ContravariantMonoidal[Predicate]", ContravariantMonoidalTests[Predicate].contravariantMonoidal[Int, Int, Int]) { - implicit val predicateMonoid = ContravariantMonoidal.monoid[Predicate, Int] + implicit val predicateMonoid = ContravariantMonoidal[Predicate].monoid[Int] checkAll("ContravariantMonoidal[Predicate].monoid", MonoidTests[Predicate[Int]].monoid) } { - implicit val predicateSemigroup = ContravariantSemigroupal.semigroup[Predicate, Int] + implicit val predicateSemigroup = ContravariantSemigroupal[Predicate].semigroup[Int] checkAll("ContravariantSemigroupal[Predicate].semigroup", SemigroupTests[Predicate[Int]].semigroup) } From 54430465a8150533634837ae053b47f540e28d3e Mon Sep 17 00:00:00 2001 From: Luka Jacobowitz Date: Fri, 15 Dec 2017 10:23:38 +0000 Subject: [PATCH 13/18] Remove semigroup and monoid from typeclass and rename conquer to trivial --- build.sbt | 7 ------- core/src/main/scala/cats/Applicative.scala | 4 +--- core/src/main/scala/cats/Apply.scala | 4 +--- .../main/scala/cats/ContravariantMonoidal.scala | 8 +++----- .../main/scala/cats/ContravariantSemigroupal.scala | 2 -- core/src/main/scala/cats/InvariantMonoidal.scala | 9 ++++++--- .../src/main/scala/cats/InvariantSemigroupal.scala | 10 +++++----- core/src/main/scala/cats/data/IndexedStateT.scala | 4 ++-- core/src/main/scala/cats/data/OptionT.scala | 2 +- core/src/main/scala/cats/data/WriterT.scala | 2 +- .../cats/laws/ContravariantMonoidalLaws.scala | 8 ++++---- .../test/scala/cats/tests/ContravariantSuite.scala | 4 ++-- .../tests/CsvCodecInvariantMonoidalSuite.scala | 4 ++-- tests/src/test/scala/cats/tests/ListWrapper.scala | 14 +++++++++----- 14 files changed, 37 insertions(+), 45 deletions(-) diff --git a/build.sbt b/build.sbt index 3d9f47d083..7e3ce825b4 100644 --- a/build.sbt +++ b/build.sbt @@ -324,13 +324,6 @@ def mimaSettings(moduleName: String) = Seq( exclude[ReversedMissingMethodProblem]("cats.syntax.MonadErrorSyntax.catsSyntaxMonadErrorRethrow"), exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.composeApply"), exclude[DirectMissingMethodProblem]("cats.Semigroupal.catsSemigroupalForMonoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.semigroup"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[ReversedMissingMethodProblem]("cats.ContravariantSemigroupal.semigroup"), - exclude[ReversedMissingMethodProblem]("cats.Applicative.monoid"), - exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[ReversedMissingMethodProblem]("cats.InvariantMonoidal.monoid"), - exclude[ReversedMissingMethodProblem]("cats.Apply.semigroup"), exclude[ReversedMissingMethodProblem]("cats.instances.InvariantMonoidalInstances.catsSemigroupalForMonoid"), exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.point"), exclude[DirectMissingMethodProblem]("cats.InvariantMonoidal.pure"), diff --git a/core/src/main/scala/cats/Applicative.scala b/core/src/main/scala/cats/Applicative.scala index 35709049fb..7726f2e7f3 100644 --- a/core/src/main/scala/cats/Applicative.scala +++ b/core/src/main/scala/cats/Applicative.scala @@ -187,13 +187,11 @@ import simulacrum.typeclass def whenA[A](cond: Boolean)(f: => F[A]): F[Unit] = if (cond) void(f) else pure(()) - override def monoid[A](implicit A: Monoid[A]): Monoid[F[A]] = - new ApplicativeMonoid[F, A](this, A) } object Applicative { def monoid[F[_], A](implicit f: Applicative[F], monoid: Monoid[A]): Monoid[F[A]] = - f.monoid + new ApplicativeMonoid[F, A](f, monoid) /** * Creates an applicative functor for `F`, holding domain fixed and combining diff --git a/core/src/main/scala/cats/Apply.scala b/core/src/main/scala/cats/Apply.scala index 7846e5b64e..0693019f15 100644 --- a/core/src/main/scala/cats/Apply.scala +++ b/core/src/main/scala/cats/Apply.scala @@ -80,13 +80,11 @@ trait Apply[F[_]] extends Functor[F] with InvariantSemigroupal[F] with ApplyArit val G = Apply[G] } - override def semigroup[A](implicit A: Semigroup[A]): Semigroup[F[A]] = - new ApplySemigroup[F, A](this, A) } object Apply { def semigroup[F[_], A](implicit f: Apply[F], sg: Semigroup[A]): Semigroup[F[A]] = - f.semigroup + new ApplySemigroup[F, A](f, sg) } private[cats] class ApplySemigroup[F[_], A](f: Apply[F], sg: Semigroup[A]) extends Semigroup[F[A]] { diff --git a/core/src/main/scala/cats/ContravariantMonoidal.scala b/core/src/main/scala/cats/ContravariantMonoidal.scala index 45e4d95c5f..276a7ce31e 100644 --- a/core/src/main/scala/cats/ContravariantMonoidal.scala +++ b/core/src/main/scala/cats/ContravariantMonoidal.scala @@ -13,14 +13,12 @@ import simulacrum.typeclass */ @typeclass trait ContravariantMonoidal[F[_]] extends ContravariantSemigroupal[F] with InvariantMonoidal[F] { /** - * `conquer` produces an instance of `F` for any type `A` + * `trivial` produces an instance of `F` for any type `A` * that is trivial with respect to `contramap2` along * the diagonal */ - def conquer[A]: F[A] = contramap(unit)(_ => ()) + def trivial[A]: F[A] = contramap(unit)(_ => ()) - override def monoid[A](implicit A: Monoid[A]): Monoid[F[A]] = - ContravariantMonoidal.monoid(this) } object ContravariantMonoidal extends SemigroupalArityFunctions { def monoid[F[_], A](implicit f: ContravariantMonoidal[F]): Monoid[F[A]] = @@ -28,5 +26,5 @@ object ContravariantMonoidal extends SemigroupalArityFunctions { } private[cats] class ContravariantMonoidalMonoid[F[_], A](f: ContravariantMonoidal[F]) extends ContravariantSemigroupalSemigroup[F, A](f) with Monoid[F[A]] { - def empty: F[A] = f.conquer + def empty: F[A] = f.trivial } diff --git a/core/src/main/scala/cats/ContravariantSemigroupal.scala b/core/src/main/scala/cats/ContravariantSemigroupal.scala index dd03358964..77910a31e0 100644 --- a/core/src/main/scala/cats/ContravariantSemigroupal.scala +++ b/core/src/main/scala/cats/ContravariantSemigroupal.scala @@ -13,8 +13,6 @@ import simulacrum.typeclass def G = Functor[G] } - override def semigroup[A](implicit A: Semigroup[A]): Semigroup[F[A]] = - ContravariantSemigroupal.semigroup(this) } object ContravariantSemigroupal extends SemigroupalArityFunctions { diff --git a/core/src/main/scala/cats/InvariantMonoidal.scala b/core/src/main/scala/cats/InvariantMonoidal.scala index 61b6a827d3..d5eeb5498c 100644 --- a/core/src/main/scala/cats/InvariantMonoidal.scala +++ b/core/src/main/scala/cats/InvariantMonoidal.scala @@ -23,12 +23,15 @@ import simulacrum.typeclass def unit: F[Unit] + +} + +object InvariantMonoidal { /** * Gives a `Monoid` instance if A itself has a `Monoid` instance. */ - def monoid[A](implicit A: Monoid[A]): Monoid[F[A]] = - new InvariantMonoidalMonoid[F, A](this, A) - + def monoid[F[_], A](implicit F: InvariantMonoidal[F], A: Monoid[A]): Monoid[F[A]] = + new InvariantMonoidalMonoid[F, A](F, A) } diff --git a/core/src/main/scala/cats/InvariantSemigroupal.scala b/core/src/main/scala/cats/InvariantSemigroupal.scala index 53e930358f..a323f933a7 100644 --- a/core/src/main/scala/cats/InvariantSemigroupal.scala +++ b/core/src/main/scala/cats/InvariantSemigroupal.scala @@ -14,16 +14,16 @@ import simulacrum.typeclass def G = Apply[G] } +} + +object InvariantSemigroupal extends SemigroupalArityFunctions { /** * Gives a `Semigroup` instance if A itself has a `Semigroup` instance. */ - def semigroup[A](implicit A: Semigroup[A]): Semigroup[F[A]] = - new InvariantSemigroupalSemigroup[F, A](this, A) - + def semigroup[F[_], A](implicit F: InvariantSemigroupal[F], A: Semigroup[A]): Semigroup[F[A]] = + new InvariantSemigroupalSemigroup[F, A](F, A) } -object InvariantSemigroupal extends SemigroupalArityFunctions - private[cats] class InvariantSemigroupalSemigroup[F[_], A](f: InvariantSemigroupal[F], sg: Semigroup[A]) extends Semigroup[F[A]] { def combine(a: F[A], b: F[A]): F[A] = InvariantSemigroupal.imap2(a, b)(sg.combine)(a => (a, a))(f, f) diff --git a/core/src/main/scala/cats/data/IndexedStateT.scala b/core/src/main/scala/cats/data/IndexedStateT.scala index 9718d0b19d..4a66cac56e 100644 --- a/core/src/main/scala/cats/data/IndexedStateT.scala +++ b/core/src/main/scala/cats/data/IndexedStateT.scala @@ -388,10 +388,10 @@ private[data] sealed abstract class IndexedStateTContravariantMonoidal[F[_], S] implicit def G: Applicative[F] override def unit: IndexedStateT[F, S, S, Unit] = - IndexedStateT.applyF(G.pure((s: S) => F.conquer[(S, Unit)])) + IndexedStateT.applyF(G.pure((s: S) => F.trivial[(S, Unit)])) override def contramap[A, B](fa: IndexedStateT[F, S, S, A])(f: B => A): IndexedStateT[F, S, S, B] = - contramap2(fa, conquer)(((a: A) => (a, a)) compose f) + contramap2(fa, trivial)(((a: A) => (a, a)) compose f) override def product[A, B](fa: IndexedStateT[F, S, S, A], fb: IndexedStateT[F, S, S, B]): IndexedStateT[F, S, S, (A, B)] = contramap2(fa, fb)(identity) diff --git a/core/src/main/scala/cats/data/OptionT.scala b/core/src/main/scala/cats/data/OptionT.scala index 64d213ab4b..106891bcbe 100644 --- a/core/src/main/scala/cats/data/OptionT.scala +++ b/core/src/main/scala/cats/data/OptionT.scala @@ -300,7 +300,7 @@ private trait OptionTMonadError[F[_], E] extends MonadError[OptionT[F, ?], E] wi private trait OptionTContravariantMonoidal[F[_]] extends ContravariantMonoidal[OptionT[F, ?]] { def F: ContravariantMonoidal[F] - override def unit: OptionT[F, Unit] = OptionT(F.conquer) + override def unit: OptionT[F, Unit] = OptionT(F.trivial) override def contramap[A, B](fa: OptionT[F, A])(f: B => A): OptionT[F, B] = OptionT(F.contramap(fa.value)(_ map f)) diff --git a/core/src/main/scala/cats/data/WriterT.scala b/core/src/main/scala/cats/data/WriterT.scala index 95ad8a7eed..ad5a797363 100644 --- a/core/src/main/scala/cats/data/WriterT.scala +++ b/core/src/main/scala/cats/data/WriterT.scala @@ -378,7 +378,7 @@ private[data] sealed trait WriterTAlternative[F[_], L] extends Alternative[Write private[data] sealed trait WriterTContravariantMonoidal[F[_], L] extends ContravariantMonoidal[WriterT[F, L, ?]] { implicit def F0: ContravariantMonoidal[F] - override def unit: WriterT[F, L, Unit] = WriterT(F0.conquer[(L, Unit)]) + override def unit: WriterT[F, L, Unit] = WriterT(F0.trivial[(L, Unit)]) override def contramap[A, B](fa: WriterT[F, L, A])(f: B => A): WriterT[F, L, B] = WriterT(F0.contramap(fa.run)((d: (L, B)) => (d._1, f(d._2)))) diff --git a/laws/src/main/scala/cats/laws/ContravariantMonoidalLaws.scala b/laws/src/main/scala/cats/laws/ContravariantMonoidalLaws.scala index ad0846fd42..ef99653482 100644 --- a/laws/src/main/scala/cats/laws/ContravariantMonoidalLaws.scala +++ b/laws/src/main/scala/cats/laws/ContravariantMonoidalLaws.scala @@ -12,16 +12,16 @@ trait ContravariantMonoidalLaws[F[_]] extends ContravariantSemigroupalLaws[F] { implicit override def F: ContravariantMonoidal[F] def contravariantMonoidalUnitRight[A](fa: F[A]): IsEq[F[A]] = - (fa, F.conquer[A]).contramapN(delta[A]) <-> fa + (fa, F.trivial[A]).contramapN(delta[A]) <-> fa def contravariantMonoidalUnitLeft[A](fa: F[A]): IsEq[F[A]] = - (F.conquer[A], fa).contramapN(delta[A]) <-> fa + (F.trivial[A], fa).contramapN(delta[A]) <-> fa def contravariantMonoidalContramap2CompatibleContramapLeft[A, B, C](fa: F[A], f: B => (A, C)): IsEq[F[B]] = - (fa, F.conquer[C]).contramapN(f) <-> fa.contramap(f andThen (_._1)) + (fa, F.trivial[C]).contramapN(f) <-> fa.contramap(f andThen (_._1)) def contravariantMonoidalContramap2CompatibleContramapRight[A, B, C](fa: F[A], f: C => (B, A)): IsEq[F[C]] = - (F.conquer[B], fa).contramapN(f) <-> fa.contramap(f andThen (_._2)) + (F.trivial[B], fa).contramapN(f) <-> fa.contramap(f andThen (_._2)) } object ContravariantMonoidalLaws { diff --git a/tests/src/test/scala/cats/tests/ContravariantSuite.scala b/tests/src/test/scala/cats/tests/ContravariantSuite.scala index a70200d36a..3524633c45 100644 --- a/tests/src/test/scala/cats/tests/ContravariantSuite.scala +++ b/tests/src/test/scala/cats/tests/ContravariantSuite.scala @@ -43,11 +43,11 @@ class ContravariantSuite extends CatsSuite { checkAll("ContravariantMonoidal[Predicate]", ContravariantMonoidalTests[Predicate].contravariantMonoidal[Int, Int, Int]) { - implicit val predicateMonoid = ContravariantMonoidal[Predicate].monoid[Int] + implicit val predicateMonoid = ContravariantMonoidal.monoid[Predicate, Int] checkAll("ContravariantMonoidal[Predicate].monoid", MonoidTests[Predicate[Int]].monoid) } { - implicit val predicateSemigroup = ContravariantSemigroupal[Predicate].semigroup[Int] + implicit val predicateSemigroup = ContravariantSemigroupal.semigroup[Predicate, Int] checkAll("ContravariantSemigroupal[Predicate].semigroup", SemigroupTests[Predicate[Int]].semigroup) } diff --git a/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala b/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala index 062c1f52cd..96cbf7d18d 100644 --- a/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala +++ b/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala @@ -95,12 +95,12 @@ class CsvCodecInvariantMonoidalSuite extends CatsSuite { checkAll("InvariantMonoidal[CsvCodec]", SerializableTests.serializable(InvariantMonoidal[CsvCodec])) { - implicit val csvMonoid = InvariantMonoidal[CsvCodec].monoid[Int] + implicit val csvMonoid = InvariantMonoidal.monoid[CsvCodec, Int] checkAll("InvariantMonoidal[CsvCodec].monoid", MonoidTests[CsvCodec[Int]].monoid) } { - implicit val csvSemigroup = InvariantSemigroupal[CsvCodec].semigroup[Int] + implicit val csvSemigroup = InvariantSemigroupal.semigroup[CsvCodec, Int] checkAll("InvariantSemigroupal[CsvCodec].semigroup", SemigroupTests[CsvCodec[Int]].semigroup) } } diff --git a/tests/src/test/scala/cats/tests/ListWrapper.scala b/tests/src/test/scala/cats/tests/ListWrapper.scala index 13a39a259d..3aa5a6fa37 100644 --- a/tests/src/test/scala/cats/tests/ListWrapper.scala +++ b/tests/src/test/scala/cats/tests/ListWrapper.scala @@ -42,10 +42,10 @@ object ListWrapper { def eqv[A : Eq]: Eq[ListWrapper[A]] = Eq.by(_.list) - val traverse: Traverse[ListWrapper] with InvariantSemigroupal[ListWrapper] = { + val traverse: Traverse[ListWrapper] = { val F = Traverse[List] - new Traverse[ListWrapper] with InvariantSemigroupal[ListWrapper] { + new Traverse[ListWrapper] { def foldLeft[A, B](fa: ListWrapper[A], b: B)(f: (B, A) => B): B = F.foldLeft(fa.list, b)(f) def foldRight[A, B](fa: ListWrapper[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = @@ -53,8 +53,6 @@ object ListWrapper { def traverse[G[_], A, B](fa: ListWrapper[A])(f: A => G[B])(implicit G0: Applicative[G]): G[ListWrapper[B]] = { G0.map(F.traverse(fa.list)(f))(ListWrapper.apply) } - def product[A, B](fa: ListWrapper[A], fb: ListWrapper[B]): ListWrapper[(A, B)] = - ListWrapper(fa.list.flatMap(a => fb.list.map(b => (a, b)))) } } @@ -62,7 +60,13 @@ object ListWrapper { val functor: Functor[ListWrapper] = traverse - val invariant: InvariantSemigroupal[ListWrapper] = traverse + val invariant: InvariantSemigroupal[ListWrapper] = new InvariantSemigroupal[ListWrapper] { + def product[A, B](fa: ListWrapper[A], fb: ListWrapper[B]): ListWrapper[(A, B)] = + ListWrapper(fa.list.flatMap(a => fb.list.map(b => (a, b)))) + + def imap[A, B](fa: ListWrapper[A])(f: A => B)(g: B => A) = + ListWrapper(fa.list.map(f)) + } val semigroupK: SemigroupK[ListWrapper] = new SemigroupK[ListWrapper] { From 1a10366cb0247450376573f919933da9cbf7bb0b Mon Sep 17 00:00:00 2001 From: Luka Jacobowitz Date: Sat, 16 Dec 2017 19:22:48 +0000 Subject: [PATCH 14/18] Remove unecceasry instances --- core/src/main/scala/cats/instances/invariant.scala | 9 +++------ core/src/main/scala/cats/instances/order.scala | 4 +++- core/src/main/scala/cats/instances/ordering.scala | 6 +++--- tests/src/test/scala/cats/tests/ListWrapper.scala | 4 +++- tests/src/test/scala/cats/tests/NestedSuite.scala | 2 +- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/core/src/main/scala/cats/instances/invariant.scala b/core/src/main/scala/cats/instances/invariant.scala index f8c43c4c7f..e683941543 100644 --- a/core/src/main/scala/cats/instances/invariant.scala +++ b/core/src/main/scala/cats/instances/invariant.scala @@ -1,6 +1,7 @@ package cats.instances import cats.kernel._ +import cats.kernel.instances.unit._ import cats.{InvariantMonoidal, Monoid, InvariantSemigroupal} trait InvariantMonoidalInstances { @@ -27,9 +28,7 @@ trait InvariantMonoidalInstances { def combine(x: B, y: B): B = f(fa.combine(g(x), g(y))) } - def unit: Semigroup[Unit] = new Semigroup[Unit] { - def combine(x: Unit, y: Unit): Unit = () - } + def unit: Semigroup[Unit] = implicitly } implicit val catsInvariantMonoidalCommutativeSemigroup: InvariantMonoidal[CommutativeSemigroup] = new InvariantMonoidal[CommutativeSemigroup] { @@ -41,9 +40,7 @@ trait InvariantMonoidalInstances { def combine(x: B, y: B): B = f(fa.combine(g(x), g(y))) } - def unit: CommutativeSemigroup[Unit] = new CommutativeSemigroup[Unit] { - def combine(x: Unit, y: Unit): Unit = () - } + def unit: CommutativeSemigroup[Unit] = implicitly } } diff --git a/core/src/main/scala/cats/instances/order.scala b/core/src/main/scala/cats/instances/order.scala index c3861ce1eb..eb4d343e45 100644 --- a/core/src/main/scala/cats/instances/order.scala +++ b/core/src/main/scala/cats/instances/order.scala @@ -1,13 +1,15 @@ package cats package instances +import cats.kernel.instances.unit._ + trait OrderInstances extends cats.kernel.OrderToOrderingConversion { implicit val catsContravariantMonoidalForOrder: ContravariantMonoidal[Order] = new ContravariantMonoidal[Order] { /** * Provides trivial order */ - def unit: Order[Unit] = Order.from[Unit]((x: Unit, y: Unit) => 0) + def unit: Order[Unit] = Order[Unit] /** Derive an `Order` for `B` given an `Order[A]` and a function `B => A`. * * Note: resulting instances are law-abiding only when the functions used are injective (represent a one-to-one mapping) diff --git a/core/src/main/scala/cats/instances/ordering.scala b/core/src/main/scala/cats/instances/ordering.scala index 19d1fa0678..69ef920384 100644 --- a/core/src/main/scala/cats/instances/ordering.scala +++ b/core/src/main/scala/cats/instances/ordering.scala @@ -1,6 +1,8 @@ package cats package instances +import cats.kernel.instances.unit._ + trait OrderingInstances { implicit val catsContravariantMonoidalForOrdering: ContravariantMonoidal[Ordering] = new ContravariantMonoidal[Ordering] { @@ -8,9 +10,7 @@ trait OrderingInstances { * Note: resulting instances are law-abiding only when the functions used are injective (represent a one-to-one mapping) */ - def unit: Ordering[Unit] = new Ordering[Unit] { - def compare(l: Unit, r: Unit): Int = 0 - } + def unit: Ordering[Unit] = Order[Unit].toOrdering def contramap[A, B](fa: Ordering[A])(f: B => A): Ordering[B] = fa.on(f) diff --git a/tests/src/test/scala/cats/tests/ListWrapper.scala b/tests/src/test/scala/cats/tests/ListWrapper.scala index 3aa5a6fa37..212d9d61ce 100644 --- a/tests/src/test/scala/cats/tests/ListWrapper.scala +++ b/tests/src/test/scala/cats/tests/ListWrapper.scala @@ -60,7 +60,7 @@ object ListWrapper { val functor: Functor[ListWrapper] = traverse - val invariant: InvariantSemigroupal[ListWrapper] = new InvariantSemigroupal[ListWrapper] { + val invariantSemigroupal: InvariantSemigroupal[ListWrapper] = new InvariantSemigroupal[ListWrapper] { def product[A, B](fa: ListWrapper[A], fb: ListWrapper[B]): ListWrapper[(A, B)] = ListWrapper(fa.list.flatMap(a => fb.list.map(b => (a, b)))) @@ -68,6 +68,8 @@ object ListWrapper { ListWrapper(fa.list.map(f)) } + val invariant: Invariant[ListWrapper] = invariantSemigroupal + val semigroupK: SemigroupK[ListWrapper] = new SemigroupK[ListWrapper] { def combineK[A](x: ListWrapper[A], y: ListWrapper[A]): ListWrapper[A] = diff --git a/tests/src/test/scala/cats/tests/NestedSuite.scala b/tests/src/test/scala/cats/tests/NestedSuite.scala index a5b25f0242..d9061cd0d3 100644 --- a/tests/src/test/scala/cats/tests/NestedSuite.scala +++ b/tests/src/test/scala/cats/tests/NestedSuite.scala @@ -52,7 +52,7 @@ class NestedSuite extends CatsSuite { { // InvariantSemigroupal + Apply functor composition - implicit val instance = ListWrapper.invariant + implicit val instance = ListWrapper.invariantSemigroupal checkAll("Nested[ListWrapper, Option, ?]", InvariantSemigroupalTests[Nested[ListWrapper, Option, ?]].invariantSemigroupal[Int, Int, Int]) checkAll("InvariantSemigroupal[Nested[ListWrapper, Const[String, ?], ?]", From 95f58ffe14849bcf3e942f34156e5419f06d9c13 Mon Sep 17 00:00:00 2001 From: Kailuo Wang Date: Mon, 18 Dec 2017 11:10:10 -0500 Subject: [PATCH 15/18] use uinit for laws --- laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala | 8 ++++---- .../cats/laws/discipline/InvariantMonoidalTests.scala | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala b/laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala index b3a65d5ce6..528bd7ae72 100644 --- a/laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala +++ b/laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala @@ -9,11 +9,11 @@ trait InvariantMonoidalLaws[F[_]] extends InvariantSemigroupalLaws[F] { import cats.syntax.semigroupal._ import cats.syntax.invariant._ - def invariantMonoidalLeftIdentity[A, B](fa: F[A], b: B): IsEq[F[A]] = - F.point(b).product(fa).imap(_._2)(a => (b, a)) <-> fa + def invariantMonoidalLeftIdentity[A, B](fa: F[A]): IsEq[F[A]] = + F.unit.product(fa).imap(_._2)(a => ((), a)) <-> fa - def invariantMonoidalRightIdentity[A, B](fa: F[A], b: B): IsEq[F[A]] = - fa.product(F.point(b)).imap(_._1)(a => (a, b)) <-> fa + def invariantMonoidalRightIdentity[A, B](fa: F[A]): IsEq[F[A]] = + fa.product(F.unit).imap(_._1)(a => (a, ())) <-> fa def invariantMonoidalAssociativity[A, B, C](fa: F[A], fb: F[B], fc: F[C]): IsEq[F[(A, (B, C))]] = diff --git a/laws/src/main/scala/cats/laws/discipline/InvariantMonoidalTests.scala b/laws/src/main/scala/cats/laws/discipline/InvariantMonoidalTests.scala index c9240c8d37..0f868c1ebd 100644 --- a/laws/src/main/scala/cats/laws/discipline/InvariantMonoidalTests.scala +++ b/laws/src/main/scala/cats/laws/discipline/InvariantMonoidalTests.scala @@ -27,8 +27,8 @@ trait InvariantMonoidalTests[F[_]] extends InvariantSemigroupalTests[F] { val parents = Seq(invariant[A, B, C], semigroupal[A, B, C]) val bases = Seq.empty val props = Seq( - "invariant monoidal left identity" -> forAll((fa: F[A], b: B) => laws.invariantMonoidalLeftIdentity(fa, b)), - "invariant monoidal right identity" -> forAll((fa: F[A], b: B) => laws.invariantMonoidalRightIdentity(fa, b)), + "invariant monoidal left identity" -> forAll((fa: F[A]) => laws.invariantMonoidalLeftIdentity(fa)), + "invariant monoidal right identity" -> forAll((fa: F[A]) => laws.invariantMonoidalRightIdentity(fa)), "invariant monoidal associativity" -> forAll((fa: F[A], fb: F[B], fc: F[C]) => laws.invariantMonoidalAssociativity(fa, fb, fc)) ) } From 4b73af899c86242da3ea9ca77c8c2b0e0f60426c Mon Sep 17 00:00:00 2001 From: Kailuo Wang Date: Mon, 18 Dec 2017 15:06:19 -0500 Subject: [PATCH 16/18] improve test coverage --- core/src/main/scala/cats/data/Const.scala | 10 --------- .../main/scala/cats/data/IndexedStateT.scala | 4 ---- .../scala/cats/instances/partialOrder.scala | 7 ++++-- .../cats/instances/partialOrdering.scala | 6 +++-- tests/src/test/scala/cats/tests/EqSuite.scala | 22 +++++++------------ .../scala/cats/tests/IndexedStateTSuite.scala | 9 +------- .../test/scala/cats/tests/OrderSuite.scala | 8 ++++++- .../scala/cats/tests/PartialOrderSuite.scala | 7 ++++++ .../cats/tests/PartialOrderingSuite.scala | 3 +++ 9 files changed, 35 insertions(+), 41 deletions(-) diff --git a/core/src/main/scala/cats/data/Const.scala b/core/src/main/scala/cats/data/Const.scala index 97c5b033d9..631a9327cd 100644 --- a/core/src/main/scala/cats/data/Const.scala +++ b/core/src/main/scala/cats/data/Const.scala @@ -135,16 +135,6 @@ private[data] sealed abstract class ConstInstances0 extends ConstInstances1 { } private[data] sealed abstract class ConstInstances1 { - implicit def catsConstInvariantMonoidal[C: Monoid]: InvariantMonoidal[Const[C, ?]] = new InvariantMonoidal[Const[C, ?]] { - def unit: Const[C, Unit] = - Const.empty - - def imap[A, B](fa: Const[C, A])(f: A => B)(g: B => A): Const[C, B] = - fa.retag[B] - - def product[A, B](fa: Const[C, A], fb: Const[C, B]): Const[C, (A, B)] = - fa.retag[(A, B)] combine fb.retag[(A, B)] - } 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 = diff --git a/core/src/main/scala/cats/data/IndexedStateT.scala b/core/src/main/scala/cats/data/IndexedStateT.scala index e0bab8fb6c..d6b6c2e4d3 100644 --- a/core/src/main/scala/cats/data/IndexedStateT.scala +++ b/core/src/main/scala/cats/data/IndexedStateT.scala @@ -247,10 +247,6 @@ private[data] sealed abstract class IndexedStateTInstances extends IndexedStateT implicit def catsDataAlternativeForIndexedStateT[F[_], S](implicit FM: Monad[F], FA: Alternative[F]): Alternative[IndexedStateT[F, S, S, ?]] with Monad[IndexedStateT[F, S, S, ?]] = new IndexedStateTAlternative[F, S] { implicit def F = FM; implicit def G = FA } - - implicit def catsDataContravariantMonoidalForIndexedStateT[F[_], S](implicit FD: ContravariantMonoidal[F], - FA: Applicative[F]): ContravariantMonoidal[IndexedStateT[F, S, S, ?]] = - new IndexedStateTContravariantMonoidal[F, S] { implicit def F = FD; implicit def G = FA } } private[data] sealed abstract class IndexedStateTInstances1 extends IndexedStateTInstances2 { diff --git a/core/src/main/scala/cats/instances/partialOrder.scala b/core/src/main/scala/cats/instances/partialOrder.scala index 671e0b82cf..ec5024e8bc 100644 --- a/core/src/main/scala/cats/instances/partialOrder.scala +++ b/core/src/main/scala/cats/instances/partialOrder.scala @@ -1,9 +1,10 @@ package cats package instances +import cats.kernel.instances.unit._ trait PartialOrderInstances { - implicit val catsContravariantSemigroupalForPartialOrder: ContravariantSemigroupal[PartialOrder] = - new ContravariantSemigroupal[PartialOrder] { + implicit val catsContravariantMonoidalForPartialOrder: ContravariantMonoidal[PartialOrder] = + new ContravariantMonoidal[PartialOrder] { /** Derive a `PartialOrder` for `B` given a `PartialOrder[A]` and a function `B => A`. * * Note: resulting instances are law-abiding only when the functions used are injective (represent a one-to-one mapping) @@ -17,5 +18,7 @@ trait PartialOrderInstances { if (z == 0.0) fb.partialCompare(x._2, y._2) else z } } + + def unit: PartialOrder[Unit] = Order[Unit] } } diff --git a/core/src/main/scala/cats/instances/partialOrdering.scala b/core/src/main/scala/cats/instances/partialOrdering.scala index d44d33e185..3560286635 100644 --- a/core/src/main/scala/cats/instances/partialOrdering.scala +++ b/core/src/main/scala/cats/instances/partialOrdering.scala @@ -2,8 +2,8 @@ package cats package instances trait PartialOrderingInstances { - implicit val catsContravariantSemigroupalForPartialOrdering: ContravariantSemigroupal[PartialOrdering] = - new ContravariantSemigroupal[PartialOrdering] { + implicit val catsContravariantMonoidalForPartialOrdering: ContravariantMonoidal[PartialOrdering] = + new ContravariantMonoidal[PartialOrdering] { /** Derive a `PartialOrdering` for `B` given a `PartialOrdering[A]` and a function `B => A`. * * Note: resulting instances are law-abiding only when the functions used are injective (represent a one-to-one mapping) @@ -24,5 +24,7 @@ trait PartialOrderingInstances { case option => option } } + + def unit: PartialOrdering[Unit] = cats.instances.unit.catsKernelStdOrderForUnit.toOrdering } } diff --git a/tests/src/test/scala/cats/tests/EqSuite.scala b/tests/src/test/scala/cats/tests/EqSuite.scala index 56fea4358c..7b70689a01 100644 --- a/tests/src/test/scala/cats/tests/EqSuite.scala +++ b/tests/src/test/scala/cats/tests/EqSuite.scala @@ -1,26 +1,20 @@ package cats package tests -import org.scalatest._ +import cats.kernel.laws.discipline.SerializableTests +import cats.laws.discipline.ContravariantMonoidalTests +import cats.laws.discipline.arbitrary._ +import cats.laws.discipline.eq._ -class EqSuite extends FunSuite { - { - import cats.implicits._ +class EqSuite extends CatsSuite { Invariant[Eq] Contravariant[Eq] Semigroupal[Eq] ContravariantSemigroupal[Eq] - ContravariantMonoidal[Eq] - } - { - import cats.instances.eq._ - Invariant[Eq] - Contravariant[Eq] - Semigroupal[Eq] - ContravariantSemigroupal[Eq] - ContravariantMonoidal[Eq] - } + checkAll("Eq[Int]", ContravariantMonoidalTests[Eq].contravariantMonoidal[Int, Int, Int]) + checkAll("ContravariantMonoidal[Eq]", SerializableTests.serializable(ContravariantMonoidal[Eq])) + } diff --git a/tests/src/test/scala/cats/tests/IndexedStateTSuite.scala b/tests/src/test/scala/cats/tests/IndexedStateTSuite.scala index 8eef8ecedc..015e75b3fd 100644 --- a/tests/src/test/scala/cats/tests/IndexedStateTSuite.scala +++ b/tests/src/test/scala/cats/tests/IndexedStateTSuite.scala @@ -2,7 +2,7 @@ package cats package tests import cats.arrow.{Profunctor, Strong} -import cats.data.{Const, EitherT, IndexedStateT, State, StateT} +import cats.data.{EitherT, IndexedStateT, State, StateT} import cats.arrow.Profunctor import cats.kernel.instances.tuple._ @@ -372,13 +372,6 @@ class IndexedStateTSuite extends CatsSuite { SemigroupK[IndexedStateT[ListWrapper, Int, Int, ?]] } - { - // F has a ContravariantMonoidal - val SD = ContravariantMonoidal[StateT[Const[String, ?], String, ?]] - - checkAll("ContravariantMonoidal[StateT[Const[String, ?], String, ?]]", SerializableTests.serializable(SD)) - } - { implicit val iso = SemigroupalTests.Isomorphisms.invariant[State[Long, ?]] diff --git a/tests/src/test/scala/cats/tests/OrderSuite.scala b/tests/src/test/scala/cats/tests/OrderSuite.scala index d93130924b..db973db828 100644 --- a/tests/src/test/scala/cats/tests/OrderSuite.scala +++ b/tests/src/test/scala/cats/tests/OrderSuite.scala @@ -2,7 +2,10 @@ package cats package tests import Helpers.Ord -import cats.kernel.laws.discipline.OrderTests +import cats.kernel.laws.discipline.{OrderTests, SerializableTests} +import cats.laws.discipline.ContravariantMonoidalTests +import cats.laws.discipline.arbitrary._ +import cats.laws.discipline.eq._ class OrderSuite extends CatsSuite { { @@ -16,6 +19,9 @@ class OrderSuite extends CatsSuite { checkAll("Float", OrderTests[Float].order) checkAll("Long", OrderTests[Long].order) + checkAll("Order", ContravariantMonoidalTests[Order].contravariantMonoidal[Int, Int, Int]) + checkAll("ContravariantMonoidal[Order]", SerializableTests.serializable(ContravariantMonoidal[Order])) + test("order ops syntax"){ forAll { (i: Ord, j: Ord) => (i compare j) should ===(Order.compare(i, j)) diff --git a/tests/src/test/scala/cats/tests/PartialOrderSuite.scala b/tests/src/test/scala/cats/tests/PartialOrderSuite.scala index 120b75f40b..5db795ecac 100644 --- a/tests/src/test/scala/cats/tests/PartialOrderSuite.scala +++ b/tests/src/test/scala/cats/tests/PartialOrderSuite.scala @@ -2,7 +2,11 @@ package cats package tests import Helpers.POrd +import cats.kernel.laws.discipline.SerializableTests +import cats.laws.discipline.ContravariantMonoidalTests import org.scalatest.Assertion +import cats.laws.discipline.arbitrary._ +import cats.laws.discipline.eq._ class PartialOrderSuite extends CatsSuite { @@ -19,6 +23,9 @@ class PartialOrderSuite extends CatsSuite { Contravariant[PartialOrder] } + checkAll("PartialOrder[Int]", ContravariantMonoidalTests[PartialOrder].contravariantMonoidal[Int, Int, Int]) + checkAll("ContravariantMonoidal[PartialOrder]", SerializableTests.serializable(ContravariantMonoidal[PartialOrder])) + test("companion object syntax") { forAll { (i: Int, j: Int) => checkPartialCompare(PartialOrder.partialCompare(i, j), catsKernelStdOrderForInt.partialCompare(i, j)) diff --git a/tests/src/test/scala/cats/tests/PartialOrderingSuite.scala b/tests/src/test/scala/cats/tests/PartialOrderingSuite.scala index 81d3e37b2a..4e1c99d657 100644 --- a/tests/src/test/scala/cats/tests/PartialOrderingSuite.scala +++ b/tests/src/test/scala/cats/tests/PartialOrderingSuite.scala @@ -16,4 +16,7 @@ class PartialOrderingSuite extends CatsSuite { checkAll("Contravariant[PartialOrdering]", ContravariantTests[PartialOrdering].contravariant[Int, Int, Int]) checkAll("Semigroupal[PartialOrdering]", SemigroupalTests[PartialOrdering].semigroupal[Int, Int, Int]) checkAll("Contravariant[PartialOrdering]", SerializableTests.serializable(Contravariant[PartialOrdering])) + + checkAll("PartialOrdering[Int]", ContravariantMonoidalTests[PartialOrdering].contravariantMonoidal[Int, Int, Int]) + checkAll("ContravariantMonoidal[PartialOrdering]", SerializableTests.serializable(ContravariantMonoidal[PartialOrdering])) } From 18f353d68a939b9934c9849009df4f8dc27d272a Mon Sep 17 00:00:00 2001 From: LukaJCB Date: Mon, 18 Dec 2017 21:56:46 +0100 Subject: [PATCH 17/18] Add more mima exceptions --- build.sbt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/build.sbt b/build.sbt index 23c92694fb..5d44cc5e36 100644 --- a/build.sbt +++ b/build.sbt @@ -343,6 +343,17 @@ def mimaSettings(moduleName: String) = Seq( exclude[InheritedNewAbstractMethodProblem]("cats.InvariantSemigroupal.composeApply"), exclude[DirectMissingMethodProblem]("cats.Semigroupal.catsSemigroupalForMonoid"), exclude[ReversedMissingMethodProblem]("cats.instances.InvariantMonoidalInstances.catsSemigroupalForMonoid"), + exclude[DirectMissingMethodProblem]("cats.implicits.catsContravariantSemigroupalForPartialOrder"), + exclude[DirectMissingMethodProblem]("cats.instances.PartialOrderingInstances.catsContravariantSemigroupalForPartialOrdering"), + exclude[ReversedMissingMethodProblem]("cats.instances.PartialOrderingInstances.catsContravariantMonoidalForPartialOrdering"), + exclude[DirectMissingMethodProblem]("cats.instances.package#partialOrdering.catsContravariantSemigroupalForPartialOrdering"), + exclude[DirectMissingMethodProblem]("cats.instances.package#all.catsContravariantSemigroupalForPartialOrder"), + exclude[DirectMissingMethodProblem]("cats.data.ConstInstances1.catsConstInvariantMonoidal"), + exclude[ReversedMissingMethodProblem]("cats.instances.PartialOrderInstances.cats$instances$PartialOrderInstances$_setter_$catsContravariantMonoidalForPartialOrder_="), + exclude[ReversedMissingMethodProblem]("cats.instances.PartialOrderingInstances.cats$instances$PartialOrderingInstances$_setter_$catsContravariantMonoidalForPartialOrdering_="), + exclude[DirectMissingMethodProblem]("cats.instances.package#partialOrder.catsContravariantSemigroupalForPartialOrder"), + exclude[DirectMissingMethodProblem]("cats.instances.PartialOrderInstances.catsContravariantSemigroupalForPartialOrder"), + exclude[ReversedMissingMethodProblem]("cats.instances.PartialOrderInstances.catsContravariantMonoidalForPartialOrder"), exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.point"), exclude[DirectMissingMethodProblem]("cats.InvariantMonoidal.pure"), exclude[ReversedMissingMethodProblem]("cats.InvariantMonoidal.point"), From 436e4448f06eb1fe5d5757e0982b3fa31728bca2 Mon Sep 17 00:00:00 2001 From: LukaJCB Date: Mon, 18 Dec 2017 22:20:06 +0100 Subject: [PATCH 18/18] Mima --- build.sbt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.sbt b/build.sbt index 5d44cc5e36..a48a6a026e 100644 --- a/build.sbt +++ b/build.sbt @@ -348,12 +348,14 @@ def mimaSettings(moduleName: String) = Seq( exclude[ReversedMissingMethodProblem]("cats.instances.PartialOrderingInstances.catsContravariantMonoidalForPartialOrdering"), exclude[DirectMissingMethodProblem]("cats.instances.package#partialOrdering.catsContravariantSemigroupalForPartialOrdering"), exclude[DirectMissingMethodProblem]("cats.instances.package#all.catsContravariantSemigroupalForPartialOrder"), + exclude[DirectMissingMethodProblem]("cats.instances.package#all.catsContravariantSemigroupalForPartialOrdering"), exclude[DirectMissingMethodProblem]("cats.data.ConstInstances1.catsConstInvariantMonoidal"), exclude[ReversedMissingMethodProblem]("cats.instances.PartialOrderInstances.cats$instances$PartialOrderInstances$_setter_$catsContravariantMonoidalForPartialOrder_="), exclude[ReversedMissingMethodProblem]("cats.instances.PartialOrderingInstances.cats$instances$PartialOrderingInstances$_setter_$catsContravariantMonoidalForPartialOrdering_="), exclude[DirectMissingMethodProblem]("cats.instances.package#partialOrder.catsContravariantSemigroupalForPartialOrder"), exclude[DirectMissingMethodProblem]("cats.instances.PartialOrderInstances.catsContravariantSemigroupalForPartialOrder"), exclude[ReversedMissingMethodProblem]("cats.instances.PartialOrderInstances.catsContravariantMonoidalForPartialOrder"), + exclude[DirectMissingMethodProblem]("cats.implicits.catsContravariantSemigroupalForPartialOrdering"), exclude[InheritedNewAbstractMethodProblem]("cats.InvariantMonoidal.point"), exclude[DirectMissingMethodProblem]("cats.InvariantMonoidal.pure"), exclude[ReversedMissingMethodProblem]("cats.InvariantMonoidal.point"),