From 276a948ecb8621ffe2f83df9fa1a918b5dc76bb8 Mon Sep 17 00:00:00 2001 From: Cody Allen Date: Tue, 2 Apr 2019 14:17:52 -0700 Subject: [PATCH] Don't depend on random sampling to determine function equivalence (#2577) * Don't depend on random sampling to determine function equivalence This is a work in progress and there is a bit more work that should probably be done before merging this. However, I have already put a fair amount of time into this and wanted to see what people thought about it before pushing through to do all of the relevant work. Cats has a lot of instances for function-like types. When we go to check the laws for these types, we are required to supply an `Eq` instance. But defining equality for functions is awkward. So far we've been approaching this by generating a bunch of values and passing them into both functions and ensuring that we get the same results from both. This can produce false positives if two functions differ but we just happen to sample values that produce the same output in both. For some purposes, it isn't a big deal if we get some occasional false positives, because over many runs of the tests with different RNG seeds, we should eventually catch any discrepancies. But here be dragons. Some tests use the results of these equality checks on the left side of an implication, so a false positive in the equality check becomes a false _negative_ (and thus a build failure) in the test result. See [here](https://github.com/typelevel/cats/pull/1666#issuecomment-301549489) for further discussion. This is where my adventure with this PR begins. Cats builds have been timing out quite a bit recently, so I tried to reduce the number of random values that we sample when comparing two functions for equality. While this did speed up the build a little bit, it started leading to a much higher frequency of build failures due to false negatives in tests. So I started to rethink how we determine function equivalence. Instead of relying on nondeterministic behavior for equality, we can only provide function equality for functions whose domains are small enough to exhaustively check. If two functions produce the same output for the entirety of their domain, they are equivalent. I've introduced an `ExhaustiveCheck[A]` type class that is similar to `Gen[A]` but produces a `Stream[A]` of the entire domain of `A`. I made the name somewhat specific to tests as opposed to something like `Finite[A]`, because types like `Int` have a finite domain but would be prohibitively expensive to exhaustively check in tests and therefore shouldn't have an instance for this type class. I also added some `Eq` instances for function-like types whose domains have `ExhaustiveCheck` instances. For the sake of compatibility, I didn't remove the old `Eq` instances, but I've put them in a lower implicit priority scope, and I've changed the sites that were using them to use the new instances (well not quite all of them yet -- that's why this PR isn't quite complete yet). The main benefits of this change as I see it are: 1. Remove some nondeterministic behavior from the build. 2. Allow for shrinking of the number of values checked to improve build times without triggering build failures. 3. Allow for future deprecation of some problematic instances that are exposed through cats-laws but that users should probably not depend on. The main potential downside that I can think of is that we might be checking 15 examples where we were checking 50 before, which could be considered a reduction in test coverage. However, I think that all of the places where this sort of approach is used are parametric on the type, so I don't think that it should matter much that the domain for this type is much smaller. Let me know what you think. If people like this approach then I can switch over the remaining bits. * Remove ExhaustiveCheck.map method * Fix InvariantMonoidal tests * Fix tests with failing implicit resolution --- .../free/FreeInvariantMonoidalSuite.scala | 32 +-- .../src/test/scala/cats/free/FreeTSuite.scala | 13 +- .../cats/laws/discipline/Arbitrary.scala | 5 + .../main/scala/cats/laws/discipline/Eq.scala | 218 ++++++++++++++---- .../laws/discipline/ExhaustiveCheck.scala | 62 +++++ .../scala/cats/laws/discipline/MiniInt.scala | 79 +++++++ .../cats/tests/AlgebraInvariantSuite.scala | 191 +++++++++++---- .../test/scala/cats/tests/AndThenSuite.scala | 21 +- .../BinCodecInvariantMonoidalSuite.scala | 173 ++++++++++++++ .../test/scala/cats/tests/BinestedSuite.scala | 14 +- .../test/scala/cats/tests/CategorySuite.scala | 11 +- .../scala/cats/tests/CokleisliSuite.scala | 41 ++-- .../test/scala/cats/tests/ComposeSuite.scala | 11 +- .../scala/cats/tests/ContravariantSuite.scala | 15 +- .../CsvCodecInvariantMonoidalSuite.scala | 108 --------- .../test/scala/cats/tests/EitherKSuite.scala | 2 +- tests/src/test/scala/cats/tests/EqSuite.scala | 4 +- .../test/scala/cats/tests/EquivSuite.scala | 7 +- .../src/test/scala/cats/tests/FuncSuite.scala | 23 +- .../test/scala/cats/tests/FunctionSuite.scala | 47 ++-- .../IndexedReaderWriterStateTSuite.scala | 148 ++++++------ .../scala/cats/tests/IndexedStateTSuite.scala | 77 ++++--- .../cats/tests/KernelContravariantSuite.scala | 14 +- .../test/scala/cats/tests/KleisliSuite.scala | 199 ++++++---------- .../test/scala/cats/tests/MiniIntSuite.scala | 48 ++++ .../test/scala/cats/tests/NestedSuite.scala | 18 +- tests/src/test/scala/cats/tests/OpSuite.scala | 10 +- .../test/scala/cats/tests/OptionTSuite.scala | 2 +- .../test/scala/cats/tests/OptionWrapper.scala | 29 +++ .../test/scala/cats/tests/OrderSuite.scala | 4 +- .../test/scala/cats/tests/OrderingSuite.scala | 7 +- .../test/scala/cats/tests/ParallelSuite.scala | 10 +- .../scala/cats/tests/PartialOrderSuite.scala | 4 +- .../cats/tests/PartialOrderingSuite.scala | 7 +- .../scala/cats/tests/RepresentableSuite.scala | 32 +-- .../src/test/scala/cats/tests/ShowSuite.scala | 4 +- .../test/scala/cats/tests/Tuple2KSuite.scala | 4 +- .../test/scala/cats/tests/WriterTSuite.scala | 3 +- 38 files changed, 1091 insertions(+), 606 deletions(-) create mode 100644 laws/src/main/scala/cats/laws/discipline/ExhaustiveCheck.scala create mode 100644 laws/src/main/scala/cats/laws/discipline/MiniInt.scala create mode 100644 tests/src/test/scala/cats/tests/BinCodecInvariantMonoidalSuite.scala delete mode 100644 tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala create mode 100644 tests/src/test/scala/cats/tests/MiniIntSuite.scala create mode 100644 tests/src/test/scala/cats/tests/OptionWrapper.scala diff --git a/free/src/test/scala/cats/free/FreeInvariantMonoidalSuite.scala b/free/src/test/scala/cats/free/FreeInvariantMonoidalSuite.scala index 1802b449bd..6420ea6533 100644 --- a/free/src/test/scala/cats/free/FreeInvariantMonoidalSuite.scala +++ b/free/src/test/scala/cats/free/FreeInvariantMonoidalSuite.scala @@ -3,10 +3,11 @@ package tests import cats.arrow.FunctionK import cats.free.FreeInvariantMonoidal -import cats.laws.discipline.{InvariantMonoidalTests, SerializableTests} +import cats.laws.discipline.{InvariantMonoidalTests, MiniInt, SerializableTests} +import cats.laws.discipline.arbitrary._ import cats.laws.discipline.SemigroupalTests.Isomorphisms import org.scalacheck.{Arbitrary, Gen} -import cats.tests.CsvCodecInvariantMonoidalSuite._ +import cats.tests.BinCodecInvariantMonoidalSuite._ class FreeInvariantMonoidalSuite extends CatsSuite { implicit def freeInvariantMonoidalArbitrary[F[_], A](implicit F: Arbitrary[F[A]], @@ -25,24 +26,25 @@ class FreeInvariantMonoidalSuite extends CatsSuite { } } - implicit val isoFreeCsvCodec = Isomorphisms.invariant[FreeInvariantMonoidal[CsvCodec, ?]] + implicit val isoFreeBinCodec = Isomorphisms.invariant[FreeInvariantMonoidal[BinCodec, ?]] - checkAll("FreeInvariantMonoidal[CsvCodec, ?]", - InvariantMonoidalTests[FreeInvariantMonoidal[CsvCodec, ?]].invariantMonoidal[Int, Int, Int]) - checkAll("InvariantMonoidal[FreeInvariantMonoidal[CsvCodec, ?]]", - SerializableTests.serializable(InvariantMonoidal[FreeInvariantMonoidal[CsvCodec, ?]])) + checkAll("FreeInvariantMonoidal[BinCodec, ?]", + InvariantMonoidalTests[FreeInvariantMonoidal[BinCodec, ?]].invariantMonoidal[MiniInt, Boolean, Boolean]) + checkAll("InvariantMonoidal[FreeInvariantMonoidal[BinCodec, ?]]", + SerializableTests.serializable(InvariantMonoidal[FreeInvariantMonoidal[BinCodec, ?]])) test("FreeInvariantMonoidal#fold") { - val n = 2 - val i1 = numericSystemCodec(8) - val i2 = InvariantMonoidal[CsvCodec].point(n) - val iExpr = i1.product(i2.imap(_ * 2)(_ / 2)) + forAll { i1: BinCodec[MiniInt] => + val n = MiniInt.unsafeFromInt(2) + val i2 = InvariantMonoidal[BinCodec].point(n) + val iExpr = i1.product(i2.imap(_ * n)(_ / n)) - val f1 = FreeInvariantMonoidal.lift[CsvCodec, Int](i1) - val f2 = FreeInvariantMonoidal.pure[CsvCodec, Int](n) - val fExpr = f1.product(f2.imap(_ * 2)(_ / 2)) + val f1 = FreeInvariantMonoidal.lift[BinCodec, MiniInt](i1) + val f2 = FreeInvariantMonoidal.pure[BinCodec, MiniInt](n) + val fExpr = f1.product(f2.imap(_ * n)(_ / n)) - fExpr.fold should ===(iExpr) + fExpr.fold should ===(iExpr) + } } implicit val idIsInvariantMonoidal: InvariantMonoidal[Id] = new InvariantMonoidal[Id] { diff --git a/free/src/test/scala/cats/free/FreeTSuite.scala b/free/src/test/scala/cats/free/FreeTSuite.scala index 7224a7a837..29b62cc99e 100644 --- a/free/src/test/scala/cats/free/FreeTSuite.scala +++ b/free/src/test/scala/cats/free/FreeTSuite.scala @@ -5,7 +5,6 @@ import cats._ import cats.arrow.FunctionK import cats.data._ import cats.laws.discipline._ -import cats.laws.discipline.arbitrary._ import cats.tests.CatsSuite import cats.instances.option._ import org.scalacheck.{Arbitrary, Cogen, Gen} @@ -247,7 +246,7 @@ trait FreeTSuiteInstances { import cats.tests.IndexedStateTSuite._ import SemigroupalTests._ - type IntState[A] = State[Int, A] + type IntState[A] = State[MiniInt, A] type FreeTOption[A] = FreeT[Option, Option, A] type FreeTState[A] = FreeT[IntState, IntState, A] @@ -261,16 +260,6 @@ trait FreeTSuiteInstances { override def map[A, B](fa: JustFunctor[A])(f: A => B): JustFunctor[B] = JustFunctor(f(fa.a)) } - implicit val intEq: Eq[Int] = new Eq[Int] { - def eqv(a: Int, b: Int) = a == b - } - - implicit def evalEq[A: Eq]: Eq[Eval[A]] = Eval.catsEqForEval[A] - - implicit def intStateEq[A: Eq]: Eq[IntState[A]] = stateEq[Int, A] - - implicit def intStateArb[A: Arbitrary]: Arbitrary[IntState[A]] = catsLawArbitraryForState[Int, A] - implicit def freeTOptionEq[A](implicit A: Eq[A], OM: Monad[Option]): Eq[FreeTOption[A]] = new Eq[FreeTOption[A]] { def eqv(a: FreeTOption[A], b: FreeTOption[A]) = Eq[Option[A]].eqv(a.runM(identity), b.runM(identity)) } diff --git a/laws/src/main/scala/cats/laws/discipline/Arbitrary.scala b/laws/src/main/scala/cats/laws/discipline/Arbitrary.scala index 664dc28477..fa99582c5e 100644 --- a/laws/src/main/scala/cats/laws/discipline/Arbitrary.scala +++ b/laws/src/main/scala/cats/laws/discipline/Arbitrary.scala @@ -349,6 +349,11 @@ object arbitrary extends ArbitraryInstances0 { implicit def catsLawsCogenForChain[A](implicit A: Cogen[A]): Cogen[Chain[A]] = Cogen[List[A]].contramap(_.toList) + implicit val catsLawsCogenForMiniInt: Cogen[MiniInt] = + Cogen[Int].contramap(_.toInt) + + implicit val catsLawsArbitraryForMiniInt: Arbitrary[MiniInt] = + Arbitrary(Gen.oneOf(MiniInt.allValues)) } sealed private[discipline] trait ArbitraryInstances0 { diff --git a/laws/src/main/scala/cats/laws/discipline/Eq.scala b/laws/src/main/scala/cats/laws/discipline/Eq.scala index feb05bd692..c6bd200676 100644 --- a/laws/src/main/scala/cats/laws/discipline/Eq.scala +++ b/laws/src/main/scala/cats/laws/discipline/Eq.scala @@ -10,16 +10,117 @@ import cats.data.AndThen import cats.instances.boolean._ import cats.instances.int._ import cats.instances.string._ +import cats.instances.tuple._ import cats.kernel._ import cats.syntax.eq._ import org.scalacheck.Arbitrary -object eq { +object eq extends DisciplineBinCompatEqInstances { + + implicit def catsLawsEqForFn1Exhaustive[A, B](implicit A: ExhaustiveCheck[A], B: Eq[B]): Eq[A => B] = + Eq.instance((f, g) => A.allValues.forall(a => B.eqv(f(a), g(a)))) + + implicit def catsLawsEqForFn2BinCompat[A, B, C](implicit ev: Eq[((A, B)) => C]): Eq[(A, B) => C] = + Eq.by((_: (A, B) => C).tupled) + + implicit def catsLawsEqForAndThenBinCompat[A, B](implicit eqAB: Eq[A => B]): Eq[AndThen[A, B]] = + Eq.by[AndThen[A, B], A => B](identity) + + implicit def catsLawsEqForShowBinCompat[A](implicit ev: Eq[A => String]): Eq[Show[A]] = + Eq.by[Show[A], A => String](showA => a => showA.show(a)) + + implicit def catsLawsEqForEqBinCompt[A](implicit ev: Eq[(A, A) => Boolean]): Eq[Eq[A]] = + Eq.by[Eq[A], (A, A) => Boolean](e => (a1, a2) => e.eqv(a1, a2)) + + implicit def catsLawsEqForEquivBinCompat[A](implicit ev: Eq[(A, A) => Boolean]): Eq[Equiv[A]] = + Eq.by[Equiv[A], (A, A) => Boolean](e => (a1, a2) => e.equiv(a1, a2)) + + implicit def catsLawsEqForPartialOrderBinCompat[A](implicit ev: Eq[(A, A) => Option[Int]]): Eq[PartialOrder[A]] = + Eq.by[PartialOrder[A], (A, A) => Option[Int]](o => (a1, a2) => o.tryCompare(a1, a2)) + + implicit def catsLawsEqForPartialOrderingBinCompat[A]( + implicit ev: Eq[(A, A) => Option[Int]] + ): Eq[PartialOrdering[A]] = + Eq.by[PartialOrdering[A], (A, A) => Option[Int]]((o: PartialOrdering[A]) => (a1, a2) => o.tryCompare(a1, a2)) + + implicit def catsLawsEqForOrderBinCompat[A](implicit ev: Eq[(A, A) => Int]): Eq[Order[A]] = + Eq.by[Order[A], (A, A) => Int](o => (a1, a2) => o.compare(a1, a2)) + + implicit def catsLawsEqForOrderingBinCompat[A](implicit ev: Eq[(A, A) => Int]): Eq[Ordering[A]] = + Eq.by[Ordering[A], (A, A) => Int](o => (a1, a2) => o.compare(a1, a2)) + + implicit def catsLawsEqForHashBinCompat[A](implicit ev: Eq[A => Int]): Eq[Hash[A]] = + Eq.by[Hash[A], A => Int](h => a => h.hash(a)) + + implicit def catsLawsEqForSemigroupBinCompat[A](implicit ev: Eq[(A, A) => A]): Eq[Semigroup[A]] = + Eq.by[Semigroup[A], (A, A) => A](s => (a1, a2) => s.combine(a1, a2)) + + implicit def catsLawsEqForCommutativeSemigroupBinCompat[A](implicit eqA: Eq[A], + ev: Eq[(A, A) => (A, A)]): Eq[CommutativeSemigroup[A]] = + Eq.by[CommutativeSemigroup[A], (A, A) => (A, A)](s => (x, y) => (s.combine(x, y), s.combine(y, x))) + + implicit def catsLawsEqForBandBinCompat[A](implicit ev: Eq[(A, A) => (A, A)]): Eq[Band[A]] = + Eq.by[Band[A], (A, A) => (A, A)]( + f => (x, y) => (f.combine(x, y), f.combine(f.combine(x, y), y)) + ) + + implicit def catsLawsEqForGroupBinCompat[A](implicit ev1: Eq[(A, A) => (A, Boolean)], eqA: Eq[A]): Eq[Group[A]] = + Eq.by[Group[A], (A, A) => (A, Boolean)]( + f => + (x, y) => + ( + f.combine(x, y), + f.combine(f.inverse(x), x) === f.empty && f.combine(x, f.inverse(x)) === f.empty && + f.combine(f.inverse(y), y) === f.empty && f.combine(y, f.inverse(y)) === f.empty && + f.inverse(f.empty) == f.empty + ) + ) + + implicit def catsLawsEqForMonoid[A](implicit eqSA: Eq[Semigroup[A]], eqA: Eq[A]): Eq[Monoid[A]] = new Eq[Monoid[A]] { + def eqv(f: Monoid[A], g: Monoid[A]): Boolean = + eqSA.eqv(f, g) && eqA.eqv(f.empty, g.empty) + } + + implicit def catsLawsEqForSemilattice[A](implicit eqBA: Eq[Band[A]], + eqCA: Eq[CommutativeSemigroup[A]], + eqA: Eq[A]): Eq[Semilattice[A]] = + Eq.instance((f, g) => eqBA.eqv(f, g) && eqCA.eqv(f, g)) + + implicit def catsLawsEqForCommutativeMonoid[A](implicit eqSA: Eq[CommutativeSemigroup[A]], + eqMA: Eq[Monoid[A]], + eqA: Eq[A]): Eq[CommutativeMonoid[A]] = + Eq.instance((f, g) => eqSA.eqv(f, g) && eqMA.eqv(f, g)) + + implicit def catsLawsEqForBoundedSemilattice[A](implicit eqSA: Eq[Semilattice[A]], + eqCA: Eq[CommutativeMonoid[A]], + eqA: Eq[A]): Eq[BoundedSemilattice[A]] = + Eq.instance((f, g) => eqSA.eqv(f, g) && eqCA.eqv(f, g)) + + implicit def catsLawsEqForCommutativeGroup[A](implicit eqMA: Eq[CommutativeMonoid[A]], + eqGA: Eq[Group[A]], + eqA: Eq[A]): Eq[CommutativeGroup[A]] = + Eq.instance((f, g) => eqMA.eqv(f, g) && eqGA.eqv(f, g)) + + implicit def catsLawsEqForRepresentableStore[F[_]: Representable, S, A](implicit eqFA: Eq[F[A]], + eqS: Eq[S]): Eq[RepresentableStore[F, S, A]] = + Eq.instance((s1, s2) => eqFA.eqv(s1.fa, s2.fa) && eqS.eqv(s1.index, s2.index)) +} + +/** + * These instances are questionable and can lead to false positives. For the sake of compatibility, + * they haven't been removed, but they should be considered to be deprecated, and we put them in a + * lower implicit scope priority. + */ +private[discipline] trait DisciplineBinCompatEqInstances { /** - * Create an approximation of Eq[A => B] by generating 100 values for A + * Create an approximation of Eq[A => B] by generating random values for A * and comparing the application of the two functions. */ + @deprecated( + "This instance is problematic and will most likely be removed in a future version of Cats. Use catsLawsEqForFn1Exhaustive instead. See https://github.com/typelevel/cats/pull/2577 for more information.", + "1.7" + ) implicit def catsLawsEqForFn1[A, B](implicit A: Arbitrary[A], B: Eq[B]): Eq[A => B] = new Eq[A => B] { val sampleCnt: Int = if (Platform.isJvm) 50 else 30 @@ -32,37 +133,43 @@ object eq { } } - /** `Eq[AndThen]` instance, built by piggybacking on [[catsLawsEqForFn1]]. */ - implicit def catsLawsEqForAndThen[A, B](implicit A: Arbitrary[A], B: Eq[B]): Eq[AndThen[A, B]] = - Eq.instance(catsLawsEqForFn1[A, B].eqv(_, _)) - /** - * Create an approximation of Eq[(A, B) => C] by generating 100 values for A and B + * Create an approximation of Eq[(A, B) => C] by generating random values for A and B * and comparing the application of the two functions. */ + @deprecated( + "This instance is problematic and will most likely be removed in a future version of Cats. Use catsLawsEqForFn2BinCompat instead. See https://github.com/typelevel/cats/pull/2577 for more information.", + "1.7" + ) implicit def catsLawsEqForFn2[A, B, C](implicit A: Arbitrary[A], B: Arbitrary[B], C: Eq[C]): Eq[(A, B) => C] = - new Eq[(A, B) => C] { - val sampleCnt: Int = if (Platform.isJvm) 50 else 5 - - def eqv(f: (A, B) => C, g: (A, B) => C): Boolean = { - val samples = List.fill(sampleCnt)((A.arbitrary.sample, B.arbitrary.sample)).collect { - case (Some(a), Some(b)) => (a, b) - case _ => sys.error("Could not generate arbitrary values to compare two functions") - } - samples.forall { case (a, b) => C.eqv(f(a, b), g(a, b)) } - } - } + Eq.by((_: (A, B) => C).tupled)(catsLawsEqForFn1) + + /** `Eq[AndThen]` instance, built by piggybacking on [[catsLawsEqForFn1]]. */ + @deprecated( + "This instance is problematic and will most likely be removed in a future version of Cats. Use catsLawsEqForAndThenBinCompat instead. See https://github.com/typelevel/cats/pull/2577 for more information.", + "1.7" + ) + implicit def catsLawsEqForAndThen[A, B](implicit A: Arbitrary[A], B: Eq[B]): Eq[AndThen[A, B]] = + Eq.instance(catsLawsEqForFn1[A, B].eqv(_, _)) /** Create an approximation of Eq[Show[A]] by using catsLawsEqForFn1[A, String] */ + @deprecated( + "This instance is problematic and will most likely be removed in a future version of Cats. Use catsLawsEqForShowBinCompat instead. See https://github.com/typelevel/cats/pull/2577 for more information.", + "1.7" + ) implicit def catsLawsEqForShow[A: Arbitrary]: Eq[Show[A]] = Eq.by[Show[A], A => String] { showInstance => (a: A) => showInstance.show(a) - } + }(catsLawsEqForFn1) /** * Create an approximate Eq instance for some type A, by comparing * the behavior of `f(x, b)` and `f(y, b)` across many `b` samples. */ + @deprecated( + "This method is problematic and will most likely be removed in a future version of Cats. You may want to use an approach based on catsLawsEqForFn1Exhaustive instead. See https://github.com/typelevel/cats/pull/2577 for more information.", + "1.7" + ) def sampledEq[A, B: Arbitrary, C: Eq](samples: Int)(f: (A, B) => C): Eq[A] = new Eq[A] { val gen = Arbitrary.arbitrary[B] @@ -76,23 +183,47 @@ object eq { } } + @deprecated( + "This instance is problematic and will most likely be removed in a future version of Cats. Use catsLawsEqForEqBinCompt instead. See https://github.com/typelevel/cats/pull/2577 for more information.", + "1.7" + ) implicit def catsLawsEqForEq[A](implicit arbA: Arbitrary[(A, A)]): Eq[Eq[A]] = sampledEq[Eq[A], (A, A), Boolean](100) { case (e, (l, r)) => e.eqv(l, r) } + @deprecated( + "This instance is problematic and will most likely be removed in a future version of Cats. Use catsLawsEqForEquivBinCompat instead. See https://github.com/typelevel/cats/pull/2577 for more information.", + "1.7" + ) implicit def catsLawsEqForEquiv[A](implicit arbA: Arbitrary[(A, A)]): Eq[Equiv[A]] = sampledEq[Equiv[A], (A, A), Boolean](100) { case (e, (l, r)) => e.equiv(l, r) } + @deprecated( + "This instance is problematic and will most likely be removed in a future version of Cats. Use catsLawsEqForPartialOrderBinCompat instead. See https://github.com/typelevel/cats/pull/2577 for more information.", + "1.7" + ) implicit def catsLawsEqForPartialOrder[A](implicit arbA: Arbitrary[(A, A)], optIntEq: Eq[Option[Int]]): Eq[PartialOrder[A]] = sampledEq[PartialOrder[A], (A, A), Option[Int]](100) { case (p, (l, r)) => p.tryCompare(l, r) } + @deprecated( + "This instance is problematic and will most likely be removed in a future version of Cats. Use catsLawsEqForPartialOrderingBinCompat instead. See https://github.com/typelevel/cats/pull/2577 for more information.", + "1.7" + ) implicit def catsLawsEqForPartialOrdering[A](implicit arbA: Arbitrary[(A, A)], optIntEq: Eq[Option[Int]]): Eq[PartialOrdering[A]] = sampledEq[PartialOrdering[A], (A, A), Option[Int]](100) { case (p, (l, r)) => p.tryCompare(l, r) } + @deprecated( + "This instance is problematic and will most likely be removed in a future version of Cats. Use catsLawsEqForOrderBinCompat instead. See https://github.com/typelevel/cats/pull/2577 for more information.", + "1.7" + ) implicit def catsLawsEqForOrder[A](implicit arbA: Arbitrary[(A, A)]): Eq[Order[A]] = sampledEq[Order[A], (A, A), Int](100) { case (p, (l, r)) => p.compare(l, r) } + @deprecated( + "This instance is problematic and will most likely be removed in a future version of Cats. Use catsLawsEqForOrderingBinCompat instead. See https://github.com/typelevel/cats/pull/2577 for more information.", + "1.7" + ) implicit def catsLawsEqForOrdering[A](implicit arbA: Arbitrary[(A, A)]): Eq[Ordering[A]] = sampledEq[Ordering[A], (A, A), Int](100) { case (p, (l, r)) => p.compare(l, r) } @@ -100,6 +231,10 @@ object eq { * Creates an approximation of Eq[Hash[A]] by generating 100 values for A * and comparing the application of the two hash functions. */ + @deprecated( + "This instance is problematic and will most likely be removed in a future version of Cats. Use catsLawsEqForHashBinCompat instead. See https://github.com/typelevel/cats/pull/2577 for more information.", + "1.7" + ) implicit def catsLawsEqForHash[A](implicit arbA: Arbitrary[A]): Eq[Hash[A]] = new Eq[Hash[A]] { def eqv(f: Hash[A], g: Hash[A]): Boolean = { val samples = List.fill(100)(arbA.arbitrary.sample).collect { @@ -116,11 +251,19 @@ object eq { * Create an approximation of Eq[Semigroup[A]] by generating values for A * and comparing the application of the two combine functions. */ + @deprecated( + "This instance is problematic and will most likely be removed in a future version of Cats. Use catsLawsEqForSemigroupBinCompat instead. See https://github.com/typelevel/cats/pull/2577 for more information.", + "1.7" + ) implicit def catsLawsEqForSemigroup[A](implicit arbAA: Arbitrary[(A, A)], eqA: Eq[A]): Eq[Semigroup[A]] = { val instance: Eq[((A, A)) => A] = catsLawsEqForFn1[(A, A), A] Eq.by[Semigroup[A], ((A, A)) => A](f => Function.tupled((x, y) => f.combine(x, y)))(instance) } + @deprecated( + "This instance is problematic and will most likely be removed in a future version of Cats. Use catsLawsEqForCommutativeSemigroupBinCompat instead. See https://github.com/typelevel/cats/pull/2577 for more information.", + "1.7" + ) implicit def catsLawsEqForCommutativeSemigroup[A](implicit arbAA: Arbitrary[(A, A)], eqA: Eq[A]): Eq[CommutativeSemigroup[A]] = { implicit val eqABool: Eq[(A, Boolean)] = Eq.instance { @@ -132,6 +275,10 @@ object eq { )(catsLawsEqForFn1[(A, A), (A, Boolean)]) } + @deprecated( + "This instance is problematic and will most likely be removed in a future version of Cats. Use catsLawsEqForBandBinCompat instead. See https://github.com/typelevel/cats/pull/2577 for more information.", + "1.7" + ) implicit def catsLawsEqForBand[A](implicit arbAA: Arbitrary[(A, A)], eqSA: Eq[Semigroup[A]], eqA: Eq[A]): Eq[Band[A]] = @@ -139,26 +286,10 @@ object eq { f => Function.tupled((x, y) => f.combine(x, y) === f.combine(f.combine(x, y), y)) )(catsLawsEqForFn1[(A, A), Boolean]) - implicit def catsLawsEqForMonoid[A](implicit eqSA: Eq[Semigroup[A]], eqA: Eq[A]): Eq[Monoid[A]] = new Eq[Monoid[A]] { - def eqv(f: Monoid[A], g: Monoid[A]): Boolean = - eqSA.eqv(f, g) && eqA.eqv(f.empty, g.empty) - } - - implicit def catsLawsEqForSemilattice[A](implicit eqBA: Eq[Band[A]], - eqCA: Eq[CommutativeSemigroup[A]], - eqA: Eq[A]): Eq[Semilattice[A]] = - Eq.instance((f, g) => eqBA.eqv(f, g) && eqCA.eqv(f, g)) - - implicit def catsLawsEqForCommutativeMonoid[A](implicit eqSA: Eq[CommutativeSemigroup[A]], - eqMA: Eq[Monoid[A]], - eqA: Eq[A]): Eq[CommutativeMonoid[A]] = - Eq.instance((f, g) => eqSA.eqv(f, g) && eqMA.eqv(f, g)) - - implicit def catsLawsEqForBoundedSemilattice[A](implicit eqSA: Eq[Semilattice[A]], - eqCA: Eq[CommutativeMonoid[A]], - eqA: Eq[A]): Eq[BoundedSemilattice[A]] = - Eq.instance((f, g) => eqSA.eqv(f, g) && eqCA.eqv(f, g)) - + @deprecated( + "This instance is problematic and will most likely be removed in a future version of Cats. Use catsLawsEqForGroupBinCompat instead. See https://github.com/typelevel/cats/pull/2577 for more information.", + "1.7" + ) implicit def catsLawsEqForGroup[A](implicit arbAA: Arbitrary[(A, A)], eqMA: Eq[Monoid[A]], eqA: Eq[A]): Eq[Group[A]] = { @@ -181,13 +312,4 @@ object eq { Eq.instance((f, g) => eqMA.eqv(f, g) && inverseEq.eqv(f, g)) } - - implicit def catsLawsEqForCommutativeGroup[A](implicit eqMA: Eq[CommutativeMonoid[A]], - eqGA: Eq[Group[A]], - eqA: Eq[A]): Eq[CommutativeGroup[A]] = - Eq.instance((f, g) => eqMA.eqv(f, g) && eqGA.eqv(f, g)) - - implicit def catsLawsEqForRepresentableStore[F[_]: Representable, S, A](implicit eqFA: Eq[F[A]], - eqS: Eq[S]): Eq[RepresentableStore[F, S, A]] = - Eq.instance((s1, s2) => eqFA.eqv(s1.fa, s2.fa) && eqS.eqv(s1.index, s2.index)) } diff --git a/laws/src/main/scala/cats/laws/discipline/ExhaustiveCheck.scala b/laws/src/main/scala/cats/laws/discipline/ExhaustiveCheck.scala new file mode 100644 index 0000000000..f5446c6f1c --- /dev/null +++ b/laws/src/main/scala/cats/laws/discipline/ExhaustiveCheck.scala @@ -0,0 +1,62 @@ +package cats +package laws +package discipline + +/** + * An `ExhuastiveCheck[A]` instance can be used similarly to a Scalacheck + * `Gen[A]` instance, but differs in that it generates a `Stream` of the entire + * domain of values as opposed to generating a random sampling of values. + */ +trait ExhaustiveCheck[A] extends Serializable { self => + def allValues: Stream[A] +} + +object ExhaustiveCheck { + def apply[A](implicit A: ExhaustiveCheck[A]): ExhaustiveCheck[A] = A + + def instance[A](values: Stream[A]): ExhaustiveCheck[A] = new ExhaustiveCheck[A] { + val allValues: Stream[A] = values + } + + implicit val catsLawsExhaustiveCheckForBoolean: ExhaustiveCheck[Boolean] = + instance(Stream(false, true)) + + implicit val catsLawsExhaustiveCheckForSetBoolean: ExhaustiveCheck[Set[Boolean]] = + forSet[Boolean] + + /** + * Warning: the domain of (A, B) is the cross-product of the domain of `A` and the domain of `B`. + */ + implicit def catsLawsExhaustiveCheckForTuple2[A, B](implicit A: ExhaustiveCheck[A], + B: ExhaustiveCheck[B]): ExhaustiveCheck[(A, B)] = + instance(A.allValues.flatMap(a => B.allValues.map(b => (a, b)))) + + /** + * Warning: the domain of (A, B, C) is the cross-product of the 3 domains. + */ + implicit def catsLawsExhaustiveCheckForTuple3[A, B, C](implicit A: ExhaustiveCheck[A], + B: ExhaustiveCheck[B], + C: ExhaustiveCheck[C]): ExhaustiveCheck[(A, B, C)] = + instance( + for { + a <- A.allValues + b <- B.allValues + c <- C.allValues + } yield (a, b, c) + ) + + implicit def catsLawsExhaustiveCheckForEither[A, B](implicit A: ExhaustiveCheck[A], + B: ExhaustiveCheck[B]): ExhaustiveCheck[Either[A, B]] = + instance(A.allValues.map(Left(_)) ++ B.allValues.map(Right(_))) + + implicit def catsLawsExhaustiveCheckForOption[A](implicit A: ExhaustiveCheck[A]): ExhaustiveCheck[Option[A]] = + instance(Stream.cons(None, A.allValues.map(Some(_)))) + + /** + * Creates an `ExhaustiveCheck[Set[A]]` given an `ExhaustiveCheck[A]` by computing the powerset of + * values. Note that if there are `n` elements in the domain of `A` there will be `2^n` elements + * in the domain of `Set[A]`, so use this only on small domains. + */ + def forSet[A](implicit A: ExhaustiveCheck[A]): ExhaustiveCheck[Set[A]] = + instance(A.allValues.toSet.subsets.toStream) +} diff --git a/laws/src/main/scala/cats/laws/discipline/MiniInt.scala b/laws/src/main/scala/cats/laws/discipline/MiniInt.scala new file mode 100644 index 0000000000..bc193ab6c4 --- /dev/null +++ b/laws/src/main/scala/cats/laws/discipline/MiniInt.scala @@ -0,0 +1,79 @@ +package cats +package laws +package discipline + +import cats.kernel.{BoundedSemilattice, CommutativeGroup, CommutativeMonoid} +import cats.instances.int._ + +/** + * Similar to `Int`, but with a much smaller domain. The exact range of [[MiniInt]] may be tuned from time to time, so + * consumers of this type should avoid depending on its exact range. + * + * `MiniInt` has integer overflow characteristics similar to `Int` (but with a smaller radix), meaning that its addition + * and multiplication are commutative and associative. + */ +final class MiniInt private (val intBits: Int) extends AnyVal with Serializable { + import MiniInt._ + + def unary_- : MiniInt = this * negativeOne + + def toInt: Int = intBits << intShift >> intShift + + def +(o: MiniInt): MiniInt = wrapped(intBits + o.intBits) + def *(o: MiniInt): MiniInt = wrapped(intBits * o.intBits) + def |(o: MiniInt): MiniInt = wrapped(intBits | o.intBits) + def /(o: MiniInt): MiniInt = wrapped(intBits / o.intBits) + + override def toString: String = s"MiniInt(toInt=$toInt, intBits=$intBits)" +} + +object MiniInt { + val bitCount: Int = 4 + val minIntValue: Int = -8 + val maxIntValue: Int = 7 + private val intShift: Int = 28 + val minValue: MiniInt = unsafeFromInt(minIntValue) + val maxValue: MiniInt = unsafeFromInt(maxIntValue) + val zero: MiniInt = unsafeFromInt(0) + val one: MiniInt = unsafeFromInt(1) + val negativeOne: MiniInt = unsafeFromInt(-1) + + def isInDomain(i: Int): Boolean = i >= minIntValue && i <= maxIntValue + + def fromInt(i: Int): Option[MiniInt] = if (isInDomain(i)) Some(unsafeFromInt(i)) else None + + def wrapped(intBits: Int): MiniInt = new MiniInt(intBits & (-1 >>> intShift)) + + def unsafeFromInt(i: Int): MiniInt = + if (isInDomain(i)) { + new MiniInt(i << intShift >>> intShift) + } else throw new IllegalArgumentException(s"Expected value between $minIntValue and $maxIntValue but got $i") + + val allValues: Stream[MiniInt] = (minIntValue to maxIntValue).map(unsafeFromInt).toStream + + implicit val catsLawsEqInstancesForMiniInt: Order[MiniInt] with Hash[MiniInt] = new Order[MiniInt] + with Hash[MiniInt] { + def hash(x: MiniInt): Int = Hash[Int].hash(x.intBits) + + def compare(x: MiniInt, y: MiniInt): Int = Order[Int].compare(x.toInt, y.toInt) + } + + implicit val catsLawsExhuastiveCheckForMiniInt: ExhaustiveCheck[MiniInt] = + ExhaustiveCheck.instance(allValues) + + val miniIntAddition: CommutativeGroup[MiniInt] = new CommutativeGroup[MiniInt] { + val empty = MiniInt.zero + def combine(x: MiniInt, y: MiniInt): MiniInt = x + y + def inverse(x: MiniInt): MiniInt = -x + } + + val miniIntMultiplication: CommutativeMonoid[MiniInt] = new CommutativeMonoid[MiniInt] { + val empty = MiniInt.one + def combine(x: MiniInt, y: MiniInt): MiniInt = x * y + } + + val miniIntOr: BoundedSemilattice[MiniInt] = new BoundedSemilattice[MiniInt] { + val empty = MiniInt.zero + def combine(x: MiniInt, y: MiniInt): MiniInt = x | y + } +} diff --git a/tests/src/test/scala/cats/tests/AlgebraInvariantSuite.scala b/tests/src/test/scala/cats/tests/AlgebraInvariantSuite.scala index ee50130e75..c62233ed22 100644 --- a/tests/src/test/scala/cats/tests/AlgebraInvariantSuite.scala +++ b/tests/src/test/scala/cats/tests/AlgebraInvariantSuite.scala @@ -4,66 +4,160 @@ package tests import cats.Invariant import cats.kernel._ import cats.kernel.laws.discipline.{SemigroupTests, MonoidTests, GroupTests, _} -import cats.laws.discipline.{InvariantMonoidalTests, InvariantSemigroupalTests, InvariantTests, SerializableTests} +import cats.laws.discipline.{ + InvariantMonoidalTests, + InvariantSemigroupalTests, + InvariantTests, + MiniInt, + SerializableTests +} +import MiniInt._ import cats.laws.discipline.eq._ +import cats.laws.discipline.arbitrary._ import org.scalacheck.{Arbitrary, Gen} class AlgebraInvariantSuite extends CatsSuite { + // working around https://github.com/typelevel/cats/issues/2701 + implicit private val eqSetBooleanTuple: Eq[(Set[Boolean], Set[Boolean])] = Eq.fromUniversalEquals + implicit private val eqSetBooleanBooleanTuple: Eq[(Set[Boolean], Boolean)] = Eq.fromUniversalEquals + + // https://github.com/typelevel/cats/issues/2725 + implicit private def commutativeMonoidForSemigroup[A]( + implicit csA: CommutativeSemigroup[A] + ): CommutativeMonoid[Option[A]] = + new CommutativeMonoid[Option[A]] { + def empty: Option[A] = None + def combine(x: Option[A], y: Option[A]): Option[A] = (x, y) match { + case (None, r) => r + case (l, None) => l + case (Some(l), Some(r)) => Some(csA.combine(l, r)) + } + } + + private def leftOptionMonoid[A]: Monoid[Option[A]] = + new Monoid[Option[A]] { + def empty: Option[A] = None + def combine(x: Option[A], y: Option[A]): Option[A] = x + } + + private def rightOptionMonoid[A]: Monoid[Option[A]] = + new Monoid[Option[A]] { + def empty: Option[A] = None + def combine(x: Option[A], y: Option[A]): Option[A] = y + } + + private val boundedSemilatticeMiniInt: BoundedSemilattice[MiniInt] = new BoundedSemilattice[MiniInt] { + def empty: MiniInt = MiniInt.zero + def combine(x: MiniInt, y: MiniInt): MiniInt = x | y + } + + private val genBoundedSemilatticeMiniInt: Gen[BoundedSemilattice[MiniInt]] = + Gen.const(miniIntOr) - val intMultiplication: CommutativeMonoid[Int] = new CommutativeMonoid[Int] { - val empty = 1 - def combine(x: Int, y: Int): Int = x * y + private val genCommutativeGroupInt: Gen[CommutativeGroup[Int]] = + Gen.const(implicitly[CommutativeGroup[Int]]) + + private val miniIntMultiplication: CommutativeMonoid[MiniInt] = new CommutativeMonoid[MiniInt] { + val empty = MiniInt.one + def combine(x: MiniInt, y: MiniInt): MiniInt = x * y } - val maxInt: Monoid[Int] = new Monoid[Int] { - val empty = Int.MinValue - def combine(x: Int, y: Int): Int = if (x > y) x else y + private val maxMiniInt: CommutativeMonoid[MiniInt] = new CommutativeMonoid[MiniInt] { + val empty = MiniInt.minValue + def combine(x: MiniInt, y: MiniInt): MiniInt = if (x > y) x else y } - val genMonoidInt: Gen[Monoid[Int]] = - Gen.oneOf(implicitly[Monoid[Int]], intMultiplication, maxInt) + private val genMonoidMiniInt: Gen[Monoid[MiniInt]] = + Gen.oneOf(miniIntAddition, miniIntMultiplication, maxMiniInt) - val genCommutativeMonoidInt: Gen[CommutativeMonoid[Int]] = - Gen.oneOf(implicitly[CommutativeMonoid[Int]], intMultiplication) + private val genMonoidOptionMiniInt: Gen[Monoid[Option[MiniInt]]] = + Gen.oneOf( + commutativeMonoidForSemigroup(miniIntAddition), + commutativeMonoidForSemigroup(miniIntMultiplication), + commutativeMonoidForSemigroup(maxMiniInt), + leftOptionMonoid[MiniInt], + rightOptionMonoid[MiniInt] + ) - val genBoundedSemilatticeSetInt: Gen[BoundedSemilattice[Set[Int]]] = - Gen.const(implicitly[BoundedSemilattice[Set[Int]]]) + private val genCommutativeMonoidMiniInt: Gen[CommutativeMonoid[MiniInt]] = + Gen.oneOf(miniIntAddition, miniIntMultiplication, maxMiniInt) - val genCommutativeGroupInt: Gen[CommutativeGroup[Int]] = - Gen.const(implicitly[CommutativeGroup[Int]]) + private val genCommutativeGroupMiniInt: Gen[CommutativeGroup[MiniInt]] = + Gen.const(miniIntAddition) + + implicit private val arbMonoidOptionMiniInt: Arbitrary[Monoid[Option[MiniInt]]] = + Arbitrary(genMonoidOptionMiniInt) + + implicit private val arbSemigroupOptionMiniInt: Arbitrary[Semigroup[Option[MiniInt]]] = + Arbitrary(genMonoidOptionMiniInt) + + implicit private val arbSemigroupMiniInt: Arbitrary[Semigroup[MiniInt]] = + Arbitrary(genMonoidMiniInt) + + implicit private val arbCommutativeMonoidMiniInt: Arbitrary[CommutativeMonoid[MiniInt]] = + Arbitrary(genCommutativeMonoidMiniInt) + + implicit private val arbCommutativeSemigroupMiniInt: Arbitrary[CommutativeSemigroup[MiniInt]] = + Arbitrary(genCommutativeMonoidMiniInt) - implicit val arbMonoidInt: Arbitrary[Monoid[Int]] = - Arbitrary(genMonoidInt) + implicit private val arbGroupMiniInt: Arbitrary[Group[MiniInt]] = + Arbitrary(genCommutativeGroupMiniInt) - implicit val arbSemigroupInt: Arbitrary[Semigroup[Int]] = - Arbitrary(genMonoidInt) + implicit private val arbCommutativeGroupMiniInt: Arbitrary[CommutativeGroup[MiniInt]] = + Arbitrary(genCommutativeGroupMiniInt) - implicit val arbCommutativeMonoidInt: Arbitrary[CommutativeMonoid[Int]] = - Arbitrary(genCommutativeMonoidInt) + private val boolAnd: CommutativeMonoid[Boolean] = new CommutativeMonoid[Boolean] { + val empty = true + def combine(x: Boolean, y: Boolean): Boolean = x && y + } + + private val boolOr: CommutativeMonoid[Boolean] = new CommutativeMonoid[Boolean] { + val empty = false + def combine(x: Boolean, y: Boolean): Boolean = x || y + } + + private val genMonoidOptionBoolean: Gen[Monoid[Option[Boolean]]] = + Gen.oneOf(commutativeMonoidForSemigroup(boolAnd), + commutativeMonoidForSemigroup(boolOr), + leftOptionMonoid[Boolean], + rightOptionMonoid[Boolean]) + + implicit private val arbMonoidOptionBoolean: Arbitrary[Monoid[Option[Boolean]]] = + Arbitrary(genMonoidOptionBoolean) + + implicit private val arbSemibroupOptionBoolean: Arbitrary[Semigroup[Option[Boolean]]] = + Arbitrary(genMonoidOptionBoolean) - implicit val arbCommutativeSemigroupInt: Arbitrary[CommutativeSemigroup[Int]] = - Arbitrary(genCommutativeMonoidInt) + private val genCommutativeMonoidBoolean: Gen[CommutativeMonoid[Boolean]] = + Gen.oneOf(boolAnd, boolOr) - implicit val arbBandSetInt: Arbitrary[Band[Set[Int]]] = - Arbitrary(genBoundedSemilatticeSetInt) + implicit private val arbCommutativeMonoidBoolean: Arbitrary[CommutativeMonoid[Boolean]] = + Arbitrary(genCommutativeMonoidBoolean) - implicit val arbSemilatticeSetInt: Arbitrary[Semilattice[Set[Int]]] = - Arbitrary(genBoundedSemilatticeSetInt) + implicit private val arbCommutativeSemigroupBoolean: Arbitrary[CommutativeSemigroup[Boolean]] = + Arbitrary(genCommutativeMonoidBoolean) - implicit val arbBoundedSemilatticeSetInt: Arbitrary[BoundedSemilattice[Set[Int]]] = - Arbitrary(genBoundedSemilatticeSetInt) + implicit private val arbBandSetMiniInt: Arbitrary[Band[MiniInt]] = + Arbitrary(genBoundedSemilatticeMiniInt) - implicit val arbGroupInt: Arbitrary[Group[Int]] = + implicit private val arbSemilatticeSetMiniInt: Arbitrary[Semilattice[MiniInt]] = + Arbitrary(genBoundedSemilatticeMiniInt) + + implicit private val arbBoundedSemilatticeSetMiniInt: Arbitrary[BoundedSemilattice[MiniInt]] = + Arbitrary(genBoundedSemilatticeMiniInt) + + implicit private val arbGroupInt: Arbitrary[Group[Int]] = Arbitrary(genCommutativeGroupInt) - implicit val arbCommutativeGroupInt: Arbitrary[CommutativeGroup[Int]] = + implicit private val arbCommutativeGroupInt: Arbitrary[CommutativeGroup[Int]] = Arbitrary(genCommutativeGroupInt) 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]) + checkAll("InvariantSemigroupal[Monoid]", + InvariantSemigroupalTests[Monoid].invariantSemigroupal[Option[MiniInt], Option[Boolean], Option[Boolean]]) { val S: Semigroup[Int] = Semigroup[Int].imap(identity)(identity) @@ -100,6 +194,10 @@ class AlgebraInvariantSuite extends CatsSuite { checkAll("CommutativeMonoid[Int]", CommutativeMonoidTests[Int](S).commutativeMonoid) } + { + checkAll("CommutativeMonoid[MiniInt]", CommutativeMonoidTests[MiniInt](miniIntAddition).commutativeMonoid) + } + { val S: CommutativeGroup[Int] = CommutativeGroup[Int].imap(identity)(identity) checkAll("CommutativeGroup[Int]", CommutativeGroupTests[Int](S).commutativeGroup) @@ -120,38 +218,45 @@ class AlgebraInvariantSuite extends CatsSuite { checkAll("BoundedSemilattice[Set[Int]]", BoundedSemilatticeTests[Set[Int]](S).boundedSemilattice) } - checkAll("Invariant[Semigroup]", InvariantTests[Semigroup].invariant[Int, Int, Int]) + checkAll("Invariant[Semigroup]", InvariantTests[Semigroup].invariant[MiniInt, Boolean, Boolean]) checkAll("Invariant[Semigroup]", SerializableTests.serializable(Invariant[Semigroup])) - checkAll("Invariant[CommutativeSemigroup]", InvariantTests[CommutativeSemigroup].invariant[Int, Int, Int]) + checkAll("Invariant[CommutativeSemigroup]", InvariantTests[CommutativeSemigroup].invariant[MiniInt, Boolean, Boolean]) checkAll("Invariant[CommutativeSemigroup]", SerializableTests.serializable(Invariant[CommutativeSemigroup])) - checkAll("Invariant[Band]", InvariantTests[Band].invariant[Set[Int], Set[Int], Set[Int]]) + checkAll("Invariant[Band]", InvariantTests[Band].invariant[MiniInt, Set[Boolean], Set[Boolean]]) checkAll("Invariant[Band]", SerializableTests.serializable(Invariant[Band])) - checkAll("Invariant[Monoid]", InvariantTests[Monoid].invariant[Int, Int, Int]) + checkAll("Invariant[Monoid]", InvariantTests[Monoid].invariant[Option[MiniInt], Boolean, Boolean]) checkAll("Invariant[Monoid]", SerializableTests.serializable(Invariant[Monoid])) - checkAll("Invariant[Semilattice]", InvariantTests[Semilattice].invariant[Set[Int], Set[Int], Set[Int]]) + Eq[Band[Set[Boolean]]] + cats.laws.discipline.ExhaustiveCheck[Set[Boolean]] + Eq[(Set[Boolean], Boolean)] + Eq[(Set[Boolean], Set[Boolean] => (Set[Boolean], Boolean))] + Eq[CommutativeSemigroup[Set[Boolean]]] + checkAll("Invariant[Semilattice]", InvariantTests[Semilattice].invariant[MiniInt, Set[Boolean], Set[Boolean]]) checkAll("Invariant[Semilattice]", SerializableTests.serializable(Invariant[Semilattice])) - checkAll("Invariant[CommutativeMonoid]", InvariantTests[CommutativeMonoid].invariant[Int, Int, Int]) + checkAll("Invariant[CommutativeMonoid]", InvariantTests[CommutativeMonoid].invariant[MiniInt, Boolean, Boolean]) checkAll("Invariant[CommutativeMonoid]", SerializableTests.serializable(Invariant[CommutativeMonoid])) - checkAll("Invariant[BoundedSemilattice]", InvariantTests[BoundedSemilattice].invariant[Set[Int], Set[Int], Set[Int]]) + checkAll("Invariant[BoundedSemilattice]", + InvariantTests[BoundedSemilattice].invariant[MiniInt, Set[Boolean], Set[Boolean]]) checkAll("Invariant[BoundedSemilattice]", SerializableTests.serializable(Invariant[BoundedSemilattice])) - checkAll("Invariant[Group]", InvariantTests[Group].invariant[Int, Int, Int]) + checkAll("Invariant[Group]", InvariantTests[Group].invariant[MiniInt, Boolean, Boolean]) checkAll("Invariant[Group]", SerializableTests.serializable(Invariant[Group])) - checkAll("Invariant[CommutativeGroup]", InvariantTests[CommutativeGroup].invariant[Int, Int, Int]) + checkAll("Invariant[CommutativeGroup]", InvariantTests[CommutativeGroup].invariant[MiniInt, Boolean, Boolean]) checkAll("Invariant[CommutativeGroup]", SerializableTests.serializable(Invariant[CommutativeGroup])) - checkAll("InvariantMonoidal[Semigroup]", InvariantMonoidalTests[Semigroup].invariantMonoidal[Int, Int, Int]) + checkAll("InvariantMonoidal[Semigroup]", + InvariantMonoidalTests[Semigroup].invariantMonoidal[Option[MiniInt], Option[Boolean], Option[Boolean]]) checkAll("InvariantMonoidal[Semigroup]", SerializableTests.serializable(InvariantMonoidal[Semigroup])) checkAll("InvariantMonoidal[CommutativeSemigroup]", - InvariantMonoidalTests[CommutativeSemigroup].invariantMonoidal[Int, Int, Int]) + InvariantMonoidalTests[CommutativeSemigroup].invariantMonoidal[MiniInt, Boolean, Boolean]) checkAll("InvariantMonoidal[CommutativeSemigroup]", SerializableTests.serializable(InvariantMonoidal[CommutativeSemigroup])) diff --git a/tests/src/test/scala/cats/tests/AndThenSuite.scala b/tests/src/test/scala/cats/tests/AndThenSuite.scala index 60f9509eca..1c8c950956 100644 --- a/tests/src/test/scala/cats/tests/AndThenSuite.scala +++ b/tests/src/test/scala/cats/tests/AndThenSuite.scala @@ -10,32 +10,31 @@ import cats.laws.discipline.eq._ import cats.laws.discipline.arbitrary._ class AndThenSuite extends CatsSuite { - { - implicit val iso = SemigroupalTests.Isomorphisms.invariant[AndThen[Int, ?]] - checkAll("AndThen[Int, Int]", SemigroupalTests[AndThen[Int, ?]].semigroupal[Int, Int, Int]) - checkAll("Semigroupal[AndThen[Int, ?]]", SerializableTests.serializable(Semigroupal[AndThen[Int, ?]])) - } + checkAll("AndThen[MiniInt, Int]", SemigroupalTests[AndThen[MiniInt, ?]].semigroupal[Int, Int, Int]) + checkAll("Semigroupal[AndThen[Int, ?]]", SerializableTests.serializable(Semigroupal[AndThen[Int, ?]])) { implicit val iso = SemigroupalTests.Isomorphisms.invariant[AndThen[?, Int]] - checkAll("AndThen[Int, Int]", ContravariantMonoidalTests[AndThen[?, Int]].contravariantMonoidal[Int, Int, Int]) + checkAll("AndThen[?, Int]", + ContravariantMonoidalTests[AndThen[?, Int]].contravariantMonoidal[MiniInt, Boolean, Boolean]) checkAll("ContravariantMonoidal[AndThen[?, Int]]", SerializableTests.serializable(ContravariantMonoidal[AndThen[?, Int]])) } - checkAll("AndThen[Int, Int]", MonadTests[AndThen[Int, ?]].monad[Int, Int, Int]) + checkAll("AndThen[MiniInt, Int]", MonadTests[AndThen[MiniInt, ?]].monad[Int, Int, Int]) checkAll("Monad[AndThen[Int, ?]]", SerializableTests.serializable(Monad[AndThen[Int, ?]])) - checkAll("AndThen[Int, Int]", CommutativeArrowTests[AndThen].commutativeArrow[Int, Int, Int, Int, Int, Int]) + checkAll("AndThen", + CommutativeArrowTests[AndThen].commutativeArrow[MiniInt, Boolean, Boolean, Boolean, Boolean, Boolean]) checkAll("Arrow[AndThen]", SerializableTests.serializable(CommutativeArrow[AndThen])) - checkAll("AndThen[Int, Int]", ChoiceTests[AndThen].choice[Int, Int, Int, Int]) + checkAll("AndThen", ChoiceTests[AndThen].choice[MiniInt, Boolean, Int, Int]) checkAll("Choice[AndThen]", SerializableTests.serializable(Choice[AndThen])) - checkAll("AndThen[Int, Int]", ArrowChoiceTests[AndThen].arrowChoice[Int, Int, Int, Int, Int, Int]) + checkAll("AndThen", ArrowChoiceTests[AndThen].arrowChoice[MiniInt, Boolean, Boolean, Boolean, Boolean, Boolean]) checkAll("ArrowChoice[AndThen]", SerializableTests.serializable(ArrowChoice[AndThen])) - checkAll("AndThen[Int, Int]", ContravariantTests[AndThen[?, Int]].contravariant[Int, Int, Int]) + checkAll("AndThen[?, Int]", ContravariantTests[AndThen[?, Int]].contravariant[MiniInt, Int, Boolean]) checkAll("Contravariant[AndThen[?, Int]]", SerializableTests.serializable(Contravariant[AndThen[?, Int]])) test("compose a chain of functions with andThen") { diff --git a/tests/src/test/scala/cats/tests/BinCodecInvariantMonoidalSuite.scala b/tests/src/test/scala/cats/tests/BinCodecInvariantMonoidalSuite.scala new file mode 100644 index 0000000000..2e6390c48e --- /dev/null +++ b/tests/src/test/scala/cats/tests/BinCodecInvariantMonoidalSuite.scala @@ -0,0 +1,173 @@ +package cats +package tests + +import cats.laws.discipline.eq._ +import cats.laws.discipline.arbitrary._ +import cats.laws.discipline.{ExhaustiveCheck, InvariantMonoidalTests, MiniInt, SerializableTests} +import cats.implicits._ +import cats.Eq +import cats.kernel.laws.discipline.{MonoidTests, SemigroupTests} +import org.scalacheck.{Arbitrary, Gen} + +object BinCodecInvariantMonoidalSuite { + final case class MiniList[+A] private (val toList: List[A]) extends AnyVal { + import MiniList.truncated + + /** + * Returns a new MiniList with a modified underlying List. Note that this truncates the returned List to ensure that + * it fits into the allowable MiniInt range. + */ + def mod[B](f: List[A] => List[B]): MiniList[B] = truncated(f(toList)) + + /** + * Append a `MiniList`. + * + * Note: this will trim the resulting list to respect the maximum list length. + */ + def ++[AA >: A](o: MiniList[AA]): MiniList[AA] = mod(_ ++ o.toList) + } + + object MiniList { + val maxLength: Int = 6 + + val nil: MiniList[Nothing] = MiniList(Nil) + def empty[A]: MiniList[A] = nil + + def truncated[A](l: List[A]): MiniList[A] = MiniList(l.take(maxLength)) + + def unsafe[A](l: List[A]): MiniList[A] = { + val inputLength = l.size + if (inputLength > maxLength) + throw new IllegalArgumentException( + s"MiniList.unsafe called with list of size $inputLength, but $maxLength is the maximum allowed size." + ) + else MiniList(l) + } + + def one[A](a: A): MiniList[A] = MiniList(a :: Nil) + + implicit def eqForMiniList[A: Eq]: Eq[MiniList[A]] = Eq.by(_.toList) + + implicit val exhaustiveCheckForMiniListBoolean: ExhaustiveCheck[MiniList[Boolean]] = + ExhaustiveCheck.instance( + for { + length <- (0 to maxLength).toStream + boolList <- List(false, true).replicateA(length).toStream + } yield MiniList.unsafe(boolList) + ) + } + + /** A small amount of binary bits */ + type Bin = MiniList[Boolean] + + /** + * Type class to read and write objects of type A to binary. + * + * Obeys `forAll { (c: BinCodec[A], a: A) => c.read(c.writes(a)) == (Some(a), List())`, + * under the assumtion that `imap(f, g)` is always called with `f` and `g` such that + * `forAll { (a: A) => g(f(a)) == a }`. + */ + trait BinCodec[A] extends Serializable { self => + + /** Reads the first value of a Bin, returning an optional value of type `A` and the remaining Bin. */ + def read(s: Bin): (Option[A], Bin) + + /** Writes a value of type `A` to Bin format. */ + def write(a: A): Bin + } + + object BinCodec { + // In tut/invariantmonoidal.md pure, product and imap are defined in + // their own trait to be introduced one by one, + trait CCPure { + def unit: BinCodec[Unit] = new BinCodec[Unit] { + def read(s: Bin): (Option[Unit], Bin) = (Some(()), s) + def write(a: Unit): Bin = MiniList.empty + } + } + + trait CCProduct { + def product[A, B](fa: BinCodec[A], fb: BinCodec[B]): BinCodec[(A, B)] = + new BinCodec[(A, B)] { + def read(s: Bin): (Option[(A, B)], Bin) = { + val (a1, s1) = fa.read(s) + val (a2, s2) = fb.read(s1) + ((a1, a2).mapN(_ -> _), s2) + } + + def write(a: (A, B)): Bin = + fa.write(a._1) ++ fb.write(a._2) + } + } + + trait CCImap { + def imap[A, B](fa: BinCodec[A])(f: A => B)(g: B => A): BinCodec[B] = + new BinCodec[B] { + def read(s: Bin): (Option[B], Bin) = { + val (a1, s1) = fa.read(s) + (a1.map(f), s1) + } + + def write(a: B): Bin = + fa.write(g(a)) + } + } + + implicit val binCodecIsInvariantMonoidal: InvariantMonoidal[BinCodec] = + new InvariantMonoidal[BinCodec] with CCPure with CCProduct with CCImap + } + + def genBinCodecForExhaustive[A](implicit exA: ExhaustiveCheck[A]): Gen[BinCodec[A]] = + for { + bitCount <- Gen.oneOf(1, 2, 3) + shuffleSeed <- Gen.choose(Long.MinValue, Long.MaxValue) + } yield { + val binValues: Stream[Bin] = Stream(false, true).replicateA(bitCount).map(MiniList.unsafe(_)) + val pairs: List[(A, Bin)] = new scala.util.Random(seed = shuffleSeed).shuffle(exA.allValues).toList.zip(binValues) + val aToBin: Map[A, Bin] = pairs.toMap + val binToA: Map[Bin, A] = pairs.map(_.swap).toMap + + new BinCodec[A] { + def read(s: Bin): (Option[A], Bin) = + (binToA.get(s.mod(_.take(bitCount))), s.mod(_.drop(bitCount))) + + def write(a: A): Bin = + aToBin.getOrElse(a, MiniList.empty) + + override def toString: String = s"BinCodec($pairs)" + } + } + + implicit val arbMiniIntCodec: Arbitrary[BinCodec[MiniInt]] = + Arbitrary(genBinCodecForExhaustive[MiniInt]) + + implicit val arbBooleanCodec: Arbitrary[BinCodec[Boolean]] = + Arbitrary(genBinCodecForExhaustive[Boolean]) + + implicit def binCodecsEq[A: Eq: ExhaustiveCheck]: Eq[BinCodec[A]] = { + val writeEq: Eq[BinCodec[A]] = Eq.by[BinCodec[A], A => Bin](_.write) + + val readEq: Eq[BinCodec[A]] = Eq.by[BinCodec[A], Bin => (Option[A], Bin)](_.read) + Eq.and(writeEq, readEq) + } +} + +class BinCodecInvariantMonoidalSuite extends CatsSuite { + // Eveything is defined in a companion object to be serializable. + import BinCodecInvariantMonoidalSuite._ + + checkAll("InvariantMonoidal[BinCodec]", InvariantMonoidalTests[BinCodec].invariantMonoidal[MiniInt, MiniInt, MiniInt]) + checkAll("InvariantMonoidal[BinCodec]", SerializableTests.serializable(InvariantMonoidal[BinCodec])) + + { + implicit val miniIntMonoid: Monoid[MiniInt] = MiniInt.miniIntAddition + implicit val binMonoid = InvariantMonoidal.monoid[BinCodec, MiniInt] + checkAll("InvariantMonoidal[BinCodec].monoid", MonoidTests[BinCodec[MiniInt]].monoid) + } + + { + implicit val miniIntSemigroup: Semigroup[MiniInt] = MiniInt.miniIntAddition + implicit val binSemigroup = InvariantSemigroupal.semigroup[BinCodec, MiniInt] + checkAll("InvariantSemigroupal[BinCodec].semigroup", SemigroupTests[BinCodec[MiniInt]].semigroup) + } +} diff --git a/tests/src/test/scala/cats/tests/BinestedSuite.scala b/tests/src/test/scala/cats/tests/BinestedSuite.scala index 88e5caa860..8580b07412 100644 --- a/tests/src/test/scala/cats/tests/BinestedSuite.scala +++ b/tests/src/test/scala/cats/tests/BinestedSuite.scala @@ -28,13 +28,17 @@ class BinestedSuite extends CatsSuite { { // Profunctor + Functor + Functor = Profunctor - implicit val instance = ListWrapper.functor + implicit val instance = OptionWrapper.functor + Eq[OptionWrapper[MiniInt] => Option[Int]] + checkAll( + "Binested[Function1, OptionWrapper, Option, ?, ?]", + ProfunctorTests[Binested[Function1, OptionWrapper, Option, ?, ?]] + .profunctor[MiniInt, Int, Int, String, String, String] + ) checkAll( - "Binested[Function1, ListWrapper, Option, ?, ?]", - ProfunctorTests[Binested[Function1, ListWrapper, Option, ?, ?]].profunctor[Int, Int, Int, String, String, String] + "Profunctor[Binested[Function1, OptionWrapper, Option, ?, ?]]", + SerializableTests.serializable(Profunctor[Binested[Function1, OptionWrapper, Option, ?, ?]]) ) - checkAll("Profunctor[Binested[Function1, ListWrapper, Option, ?, ?]]", - SerializableTests.serializable(Profunctor[Binested[Function1, ListWrapper, Option, ?, ?]])) } { diff --git a/tests/src/test/scala/cats/tests/CategorySuite.scala b/tests/src/test/scala/cats/tests/CategorySuite.scala index 5eb98a484b..0f6c62ffb9 100644 --- a/tests/src/test/scala/cats/tests/CategorySuite.scala +++ b/tests/src/test/scala/cats/tests/CategorySuite.scala @@ -4,15 +4,16 @@ package tests import cats.kernel.laws.discipline.MonoidTests import cats.arrow.Category -import cats.laws.discipline.{MonoidKTests, SerializableTests} -import cats.laws.discipline.eq.catsLawsEqForFn1 +import cats.laws.discipline.{MiniInt, MonoidKTests, SerializableTests} +import cats.laws.discipline.eq.catsLawsEqForFn1Exhaustive +import cats.laws.discipline.arbitrary.{catsLawsArbitraryForMiniInt, catsLawsCogenForMiniInt} class CategorySuite extends CatsSuite { val functionCategory = Category[Function1] - checkAll("Category[Function1].algebraK", MonoidKTests[Endo](functionCategory.algebraK).monoidK[Int]) + checkAll("Category[Function1].algebraK", MonoidKTests[Endo](functionCategory.algebraK).monoidK[MiniInt]) checkAll("Category[Function1].algebraK", SerializableTests.serializable(functionCategory.algebraK)) - val functionAlgebra = functionCategory.algebra[Int] - checkAll("Category[Function1].algebra[Int]", MonoidTests[Endo[Int]](functionAlgebra).monoid) + val functionAlgebra = functionCategory.algebra[MiniInt] + checkAll("Category[Function1].algebra[MiniInt]", MonoidTests[Endo[MiniInt]](functionAlgebra).monoid) } diff --git a/tests/src/test/scala/cats/tests/CokleisliSuite.scala b/tests/src/test/scala/cats/tests/CokleisliSuite.scala index 57e3520c0b..1d8b58baa5 100644 --- a/tests/src/test/scala/cats/tests/CokleisliSuite.scala +++ b/tests/src/test/scala/cats/tests/CokleisliSuite.scala @@ -7,7 +7,6 @@ import cats.data.{Cokleisli, NonEmptyList} import cats.laws.discipline._ import cats.laws.discipline.arbitrary._ import cats.laws.discipline.eq._ -import org.scalacheck.Arbitrary class CokleisliSuite extends SlowCatsSuite { @@ -15,54 +14,56 @@ class CokleisliSuite extends SlowCatsSuite { slowCheckConfiguration.copy(sizeRange = slowCheckConfiguration.sizeRange.min(5), minSuccessful = slowCheckConfiguration.minSuccessful.min(20)) - implicit def cokleisliEq[F[_], A, B](implicit A: Arbitrary[F[A]], FB: Eq[B]): Eq[Cokleisli[F, A, B]] = + implicit def cokleisliEq[F[_], A, B](implicit ev: Eq[F[A] => B]): Eq[Cokleisli[F, A, B]] = Eq.by[Cokleisli[F, A, B], F[A] => B](_.run) - def cokleisliEqE[F[_], A](implicit A: Arbitrary[F[A]], FA: Eq[A]): Eq[Cokleisli[F, A, A]] = - Eq.by[Cokleisli[F, A, A], F[A] => A](_.run) - implicit val iso = SemigroupalTests.Isomorphisms.invariant[Cokleisli[Option, Int, ?]] - checkAll("Cokleisli[Option, Int, Int]", SemigroupalTests[Cokleisli[Option, Int, ?]].semigroupal[Int, Int, Int]) + checkAll("Cokleisli[Option, MiniInt, Int]", + SemigroupalTests[Cokleisli[Option, MiniInt, ?]].semigroupal[Int, Int, Int]) checkAll("Semigroupal[Cokleisli[Option, Int, ?]]", SerializableTests.serializable(Semigroupal[Cokleisli[Option, Int, ?]])) - checkAll("Cokleisli[Option, Int, Int]", MonadTests[Cokleisli[Option, Int, ?]].monad[Int, Int, Int]) + checkAll("Cokleisli[Option, MiniInt, Int]", MonadTests[Cokleisli[Option, MiniInt, ?]].monad[Int, Int, Int]) checkAll("Monad[Cokleisli[Option, Int, ?]]", SerializableTests.serializable(Monad[Cokleisli[Option, Int, ?]])) - checkAll("Cokleisli[Option, Int, Int]", - ProfunctorTests[Cokleisli[Option, ?, ?]].profunctor[Int, Int, Int, Int, Int, Int]) + checkAll("Cokleisli[Option, MiniInt, Int]", + ProfunctorTests[Cokleisli[Option, ?, ?]].profunctor[MiniInt, Int, Int, Int, Int, Int]) checkAll("Profunctor[Cokleisli[Option, ?, ?]]", SerializableTests.serializable(Profunctor[Cokleisli[Option, ?, ?]])) - checkAll("Cokleisli[Option, Int, Int]", ContravariantTests[Cokleisli[Option, ?, Int]].contravariant[Int, Int, Int]) - checkAll("Contravariant[Cokleisli[Option, ?, Int]]", + checkAll("Cokleisli[Option, MiniInt, MiniInt]", + ContravariantTests[Cokleisli[Option, ?, MiniInt]].contravariant[MiniInt, MiniInt, MiniInt]) + checkAll("Contravariant[Cokleisli[Option, ?, MiniInt]]", SerializableTests.serializable(Contravariant[Cokleisli[Option, ?, Int]])) - checkAll("Cokleisli[NonEmptyList, Int, Int]", MonoidKTests[λ[α => Cokleisli[NonEmptyList, α, α]]].monoidK[Int]) + checkAll("Cokleisli[(Boolean, ?), MiniInt, MiniInt]", + MonoidKTests[λ[α => Cokleisli[(Boolean, ?), α, α]]].monoidK[MiniInt]) checkAll("MonoidK[λ[α => Cokleisli[NonEmptyList, α, α]]]", SerializableTests.serializable(MonoidK[λ[α => Cokleisli[NonEmptyList, α, α]]])) - checkAll("Cokleisli[List, Int, Int]", SemigroupKTests[λ[α => Cokleisli[List, α, α]]].semigroupK[Int]) + checkAll("Cokleisli[Option, MiniInt, MiniInt]", SemigroupKTests[λ[α => Cokleisli[Option, α, α]]].semigroupK[MiniInt]) checkAll("SemigroupK[λ[α => Cokleisli[List, α, α]]]", SerializableTests.serializable(SemigroupK[λ[α => Cokleisli[List, α, α]]])) - checkAll("Cokleisli[NonEmptyList, Int, Int]", - ArrowTests[Cokleisli[NonEmptyList, ?, ?]].arrow[Int, Int, Int, Int, Int, Int]) + checkAll("Cokleisli[(Boolean, ?), MiniInt, MiniInt]", + ArrowTests[Cokleisli[(Boolean, ?), ?, ?]].arrow[MiniInt, MiniInt, MiniInt, MiniInt, MiniInt, MiniInt]) checkAll("Arrow[Cokleisli[NonEmptyList, ?, ?]]", SerializableTests.serializable(Arrow[Cokleisli[NonEmptyList, ?, ?]])) { - implicit def cokleisliIdEq[A, B](implicit A: Arbitrary[A], FB: Eq[B]): Eq[Cokleisli[Id, A, B]] = + implicit def cokleisliIdEq[A, B](implicit evidence: Eq[A => B]): Eq[Cokleisli[Id, A, B]] = Eq.by[Cokleisli[Id, A, B], A => B](_.run) - checkAll("Cokleisli[Id, Int, Int]", - CommutativeArrowTests[Cokleisli[Id, ?, ?]].commutativeArrow[Int, Int, Int, Int, Int, Int]) + checkAll( + "Cokleisli[Id, MiniInt, MiniInt]", + CommutativeArrowTests[Cokleisli[Id, ?, ?]].commutativeArrow[MiniInt, MiniInt, MiniInt, MiniInt, MiniInt, MiniInt] + ) checkAll("CommutativeArrow[Cokleisli[Id, ?, ?]]", SerializableTests.serializable(CommutativeArrow[Cokleisli[Id, ?, ?]])) } test("contramapValue with Id consistent with lmap") { - forAll { (c: Cokleisli[Id, Int, Long], f: Char => Int) => - c.contramapValue[Char](f) should ===(c.lmap(f)) + forAll { (c: Cokleisli[Id, Int, Long], f: MiniInt => Int) => + c.contramapValue[MiniInt](f) should ===(c.lmap(f)) } } } diff --git a/tests/src/test/scala/cats/tests/ComposeSuite.scala b/tests/src/test/scala/cats/tests/ComposeSuite.scala index 1c6ca48343..07bad67dc5 100644 --- a/tests/src/test/scala/cats/tests/ComposeSuite.scala +++ b/tests/src/test/scala/cats/tests/ComposeSuite.scala @@ -3,17 +3,18 @@ package tests import cats.kernel.laws.discipline.SemigroupTests import cats.arrow.Compose -import cats.laws.discipline.{SemigroupKTests, SerializableTests} -import cats.laws.discipline.eq.catsLawsEqForFn1 +import cats.laws.discipline.{MiniInt, SemigroupKTests, SerializableTests} +import cats.laws.discipline.eq.catsLawsEqForFn1Exhaustive +import cats.laws.discipline.arbitrary._ class ComposeSuite extends CatsSuite { val functionCompose = Compose[Function1] - checkAll("Compose[Function1].algebraK", SemigroupKTests[Endo](functionCompose.algebraK).semigroupK[Int]) + checkAll("Compose[Function1].algebraK", SemigroupKTests[Endo](functionCompose.algebraK).semigroupK[MiniInt]) checkAll("Compose[Function1].algebraK", SerializableTests.serializable(functionCompose.algebraK)) - val functionAlgebra = functionCompose.algebra[Int] - checkAll("Compose[Function1].algebra[Int]", SemigroupTests[Endo[Int]](functionAlgebra).semigroup) + val functionAlgebra = functionCompose.algebra[MiniInt] + checkAll("Compose[Function1].algebra[MiniInt]", SemigroupTests[Endo[MiniInt]](functionAlgebra).semigroup) test("syntax") { (((_: Int) + 1) <<< ((_: Int) / 2))(2) should be(2) diff --git a/tests/src/test/scala/cats/tests/ContravariantSuite.scala b/tests/src/test/scala/cats/tests/ContravariantSuite.scala index 189005977f..e515a4ac41 100644 --- a/tests/src/test/scala/cats/tests/ContravariantSuite.scala +++ b/tests/src/test/scala/cats/tests/ContravariantSuite.scala @@ -3,10 +3,11 @@ package tests import cats.data.Const import cats.kernel.laws.discipline.{MonoidTests, SemigroupTests} -import cats.laws.discipline.ContravariantMonoidalTests +import cats.laws.discipline.{ContravariantMonoidalTests, ExhaustiveCheck, MiniInt} import org.scalactic.CanEqual import org.scalacheck.{Arbitrary, Cogen} import cats.laws.discipline.eq._ +import cats.laws.discipline.arbitrary._ class ContravariantSuite extends CatsSuite { @@ -33,22 +34,22 @@ class ContravariantSuite extends CatsSuite { Predicate(x => fa.run(f(x))) } - implicit def eqPredicate[A: Arbitrary]: Eq[Predicate[A]] = + implicit def eqPredicate[A: ExhaustiveCheck]: 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]) + ContravariantMonoidalTests[Predicate].contravariantMonoidal[Boolean, Boolean, Boolean]) { - implicit val predicateMonoid = ContravariantMonoidal.monoid[Predicate, Int] - checkAll("ContravariantMonoidal[Predicate].monoid", MonoidTests[Predicate[Int]].monoid) + implicit val predicateMonoid = ContravariantMonoidal.monoid[Predicate, MiniInt] + checkAll("ContravariantMonoidal[Predicate].monoid", MonoidTests[Predicate[MiniInt]].monoid) } { - implicit val predicateSemigroup = ContravariantSemigroupal.semigroup[Predicate, Int] - checkAll("ContravariantSemigroupal[Predicate].semigroup", SemigroupTests[Predicate[Int]].semigroup) + implicit val predicateSemigroup = ContravariantSemigroupal.semigroup[Predicate, MiniInt] + checkAll("ContravariantSemigroupal[Predicate].semigroup", SemigroupTests[Predicate[MiniInt]].semigroup) } } diff --git a/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala b/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala deleted file mode 100644 index b828cacb0a..0000000000 --- a/tests/src/test/scala/cats/tests/CsvCodecInvariantMonoidalSuite.scala +++ /dev/null @@ -1,108 +0,0 @@ -package cats -package tests - -import cats.laws.discipline.eq.catsLawsEqForFn1 -import cats.laws.discipline.{InvariantMonoidalTests, SerializableTests} -import cats.instances.all._ -import cats.syntax.apply._ -import cats.Eq -import cats.kernel.laws.discipline.{MonoidTests, SemigroupTests} -import org.scalacheck.{Arbitrary, Gen} - -object CsvCodecInvariantMonoidalSuite { - type CSV = List[String] - - /** - * Type class to read and write objects of type A to CSV. - * - * Obeys `forAll { (c: CsvCodec[A], a: A) => c.read(c.writes(a)) == (Some(a), List())`, - * under the assumtion that `imap(f, g)` is always called with `f` and `g` such that - * `forAll { (a: A) => g(f(a)) == a }`. - */ - trait CsvCodec[A] extends Serializable { self => - - /** Reads the first value of a CSV, returning an optional value of type `A` and the remaining CSV. */ - def read(s: CSV): (Option[A], CSV) - - /** Writes a value of type `A` to CSV format. */ - def write(a: A): CSV - } - - object CsvCodec { - // In tut/invariantmonoidal.md pure, product and imap are defined in - // their own trait to be introduced one by one, - trait CCPure { - def unit: CsvCodec[Unit] = new CsvCodec[Unit] { - def read(s: CSV): (Option[Unit], CSV) = (Some(()), s) - def write(a: Unit): CSV = List.empty - } - } - - trait CCProduct { - def product[A, B](fa: CsvCodec[A], fb: CsvCodec[B]): CsvCodec[(A, B)] = - new CsvCodec[(A, B)] { - def read(s: CSV): (Option[(A, B)], CSV) = { - val (a1, s1) = fa.read(s) - val (a2, s2) = fb.read(s1) - ((a1, a2).mapN(_ -> _), s2) - } - - def write(a: (A, B)): CSV = - fa.write(a._1) ++ fb.write(a._2) - } - } - - trait CCImap { - def imap[A, B](fa: CsvCodec[A])(f: A => B)(g: B => A): CsvCodec[B] = - new CsvCodec[B] { - def read(s: CSV): (Option[B], CSV) = { - val (a1, s1) = fa.read(s) - (a1.map(f), s1) - } - - def write(a: B): CSV = - fa.write(g(a)) - } - } - - implicit val csvCodecIsInvariantMonoidal: InvariantMonoidal[CsvCodec] = - new InvariantMonoidal[CsvCodec] with CCPure with CCProduct with CCImap - } - - def numericSystemCodec(base: Int): CsvCodec[Int] = - new CsvCodec[Int] { - def read(s: CSV): (Option[Int], CSV) = - (s.headOption.flatMap(head => scala.util.Try(Integer.parseInt(head, base)).toOption), s.drop(1)) - - def write(a: Int): CSV = - List(Integer.toString(a, base)) - } - - implicit val arbNumericSystemCodec: Arbitrary[CsvCodec[Int]] = - Arbitrary(Gen.choose(2, 16).map(numericSystemCodec)) - - implicit def csvCodecsEq[A](implicit a: Arbitrary[A], e: Eq[A]): Eq[CsvCodec[A]] = { - val writeEq: Eq[CsvCodec[A]] = Eq.by[CsvCodec[A], A => CSV](_.write)(catsLawsEqForFn1[A, CSV]) - val readEq: Eq[CsvCodec[A]] = - Eq.by[CsvCodec[A], CSV => (Option[A], CSV)](_.read)(catsLawsEqForFn1[CSV, (Option[A], CSV)]) - Eq.and(writeEq, readEq) - } -} - -class CsvCodecInvariantMonoidalSuite extends CatsSuite { - // Eveything is defined in a companion object to be serializable. - import CsvCodecInvariantMonoidalSuite._ - - 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) - } - - { - implicit val csvSemigroup = InvariantSemigroupal.semigroup[CsvCodec, Int] - checkAll("InvariantSemigroupal[CsvCodec].semigroup", SemigroupTests[CsvCodec[Int]].semigroup) - } -} diff --git a/tests/src/test/scala/cats/tests/EitherKSuite.scala b/tests/src/test/scala/cats/tests/EitherKSuite.scala index 04b63260ca..32734c9432 100644 --- a/tests/src/test/scala/cats/tests/EitherKSuite.scala +++ b/tests/src/test/scala/cats/tests/EitherKSuite.scala @@ -32,7 +32,7 @@ class EitherKSuite extends CatsSuite { checkAll("EitherK[Option, Option, Int]", EqTests[EitherK[Option, Option, Int]].eqv) checkAll("Eq[EitherK[Option, Option, Int]]", SerializableTests.serializable(Eq[EitherK[Option, Option, Int]])) - checkAll("EitherK[Show, Show, ?]", ContravariantTests[EitherK[Show, Show, ?]].contravariant[Int, Int, Int]) + checkAll("EitherK[Show, Show, ?]", ContravariantTests[EitherK[Show, Show, ?]].contravariant[MiniInt, Int, Boolean]) checkAll("Contravariant[EitherK[Show, Show, ?]]", SerializableTests.serializable(Contravariant[EitherK[Show, Show, ?]])) diff --git a/tests/src/test/scala/cats/tests/EqSuite.scala b/tests/src/test/scala/cats/tests/EqSuite.scala index 91c16adf16..6898df5828 100644 --- a/tests/src/test/scala/cats/tests/EqSuite.scala +++ b/tests/src/test/scala/cats/tests/EqSuite.scala @@ -2,7 +2,7 @@ package cats package tests import cats.kernel.laws.discipline.SerializableTests -import cats.laws.discipline.ContravariantMonoidalTests +import cats.laws.discipline.{ContravariantMonoidalTests, MiniInt} import cats.laws.discipline.arbitrary._ import cats.laws.discipline.eq._ @@ -12,7 +12,7 @@ class EqSuite extends CatsSuite { Semigroupal[Eq] ContravariantSemigroupal[Eq] - checkAll("Eq[Int]", ContravariantMonoidalTests[Eq].contravariantMonoidal[Int, Int, Int]) + checkAll("Eq", ContravariantMonoidalTests[Eq].contravariantMonoidal[MiniInt, Boolean, Boolean]) checkAll("ContravariantMonoidal[Eq]", SerializableTests.serializable(ContravariantMonoidal[Eq])) } diff --git a/tests/src/test/scala/cats/tests/EquivSuite.scala b/tests/src/test/scala/cats/tests/EquivSuite.scala index 62bf7d5fc7..a443441e42 100644 --- a/tests/src/test/scala/cats/tests/EquivSuite.scala +++ b/tests/src/test/scala/cats/tests/EquivSuite.scala @@ -13,8 +13,9 @@ class EquivSuite extends CatsSuite { ContravariantSemigroupal[Equiv] ContravariantMonoidal[Equiv] - checkAll("Contravariant[Equiv]", ContravariantTests[Equiv].contravariant[Int, Int, Int]) - checkAll("Semigroupal[Equiv]", SemigroupalTests[Equiv].semigroupal[Int, Int, Int]) - checkAll("ContravariantMonoidal[Equiv]", ContravariantMonoidalTests[Equiv].contravariantMonoidal[Int, Int, Int]) + checkAll("Contravariant[Equiv]", ContravariantTests[Equiv].contravariant[MiniInt, Int, Boolean]) + checkAll("Semigroupal[Equiv]", SemigroupalTests[Equiv].semigroupal[MiniInt, Boolean, Boolean]) + checkAll("ContravariantMonoidal[Equiv]", + ContravariantMonoidalTests[Equiv].contravariantMonoidal[MiniInt, Boolean, Boolean]) checkAll("ContravariantMonoidal[Equiv]", SerializableTests.serializable(ContravariantMonoidal[Equiv])) } diff --git a/tests/src/test/scala/cats/tests/FuncSuite.scala b/tests/src/test/scala/cats/tests/FuncSuite.scala index 47402b3449..3188a9a25b 100644 --- a/tests/src/test/scala/cats/tests/FuncSuite.scala +++ b/tests/src/test/scala/cats/tests/FuncSuite.scala @@ -6,48 +6,49 @@ import Func.appFunc import cats.Contravariant import cats.laws.discipline._ import cats.laws.discipline.arbitrary._ -import org.scalacheck.Arbitrary class FuncSuite extends CatsSuite { import cats.laws.discipline.eq._ - implicit def funcEq[F[_], A, B](implicit A: Arbitrary[A], FB: Eq[F[B]]): Eq[Func[F, A, B]] = + implicit def funcEq[F[_], A, B](implicit ev: Eq[A => F[B]]): Eq[Func[F, A, B]] = Eq.by[Func[F, A, B], A => F[B]](_.run) - implicit def appFuncEq[F[_], A, B](implicit A: Arbitrary[A], FB: Eq[F[B]]): Eq[AppFunc[F, A, B]] = + implicit def appFuncEq[F[_], A, B](implicit ev: Eq[A => F[B]]): Eq[AppFunc[F, A, B]] = Eq.by[AppFunc[F, A, B], A => F[B]](_.run) implicit val iso = SemigroupalTests.Isomorphisms.invariant[Func[Option, Int, ?]] - checkAll("Func[Option, Int, Int]", SemigroupalTests[Func[Option, Int, ?]].semigroupal[Int, Int, Int]) + checkAll("Func[Option, MiniInt, Int]", SemigroupalTests[Func[Option, MiniInt, ?]].semigroupal[Int, Int, Int]) checkAll("Semigroupal[Func[Option, Int, ?]]", SerializableTests.serializable(Semigroupal[Func[Option, Int, ?]])) { implicit val catsDataApplicativeForFunc = Func.catsDataApplicativeForFunc[Option, Int] - checkAll("Func[Option, Int, Int]", ApplicativeTests[Func[Option, Int, ?]].applicative[Int, Int, Int]) + checkAll("Func[Option, MiniInt, Int]", ApplicativeTests[Func[Option, MiniInt, ?]].applicative[Int, Int, Int]) checkAll("Applicative[Func[Option, Int, ?]]", SerializableTests.serializable(Applicative[Func[Option, Int, ?]])) } { - implicit val catsDataApplyForFunc = Func.catsDataApplyForFunc[Option, Int] - checkAll("Func[Option, Int, Int]", ApplyTests[Func[Option, Int, ?]].apply[Int, Int, Int]) + implicit val catsDataApplyForFunc = Func.catsDataApplyForFunc[Option, MiniInt] + checkAll("Func[Option, MiniInt, Int]", ApplyTests[Func[Option, MiniInt, ?]].apply[Int, Int, Int]) checkAll("Apply[Func[Option, Int, ?]]", SerializableTests.serializable(Apply[Func[Option, Int, ?]])) } { implicit val catsDataFunctorForFunc = Func.catsDataFunctorForFunc[Option, Int] - checkAll("Func[Option, Int, Int]", FunctorTests[Func[Option, Int, ?]].functor[Int, Int, Int]) + checkAll("Func[Option, MiniInt, Int]", FunctorTests[Func[Option, MiniInt, ?]].functor[Int, Int, Int]) checkAll("Functor[Func[Option, Int, ?]]", SerializableTests.serializable(Functor[Func[Option, Int, ?]])) } { - implicit val funcContravariant = Func.catsDataContravariantForFunc[Show, Int] - checkAll("Func[Show, Int, Int]", ContravariantTests[Func[Show, ?, Int]].contravariant[Int, Int, Int]) + implicit val funcContravariant = Func.catsDataContravariantForFunc[Show, MiniInt] + checkAll("Func[Show, MiniInt, MiniInt]", + ContravariantTests[Func[Show, ?, MiniInt]].contravariant[MiniInt, MiniInt, MiniInt]) checkAll("Contravariant[Func[Show, ?, Int]]", SerializableTests.serializable(Contravariant[Func[Show, ?, Int]])) } { implicit val appFuncApp = AppFunc.appFuncApplicative[Option, Int] implicit val iso = SemigroupalTests.Isomorphisms.invariant[AppFunc[Option, Int, ?]] - checkAll("AppFunc[Option, Int, Int]", ApplicativeTests[AppFunc[Option, Int, ?]].applicative[Int, Int, Int]) + checkAll("AppFunc[Option, MiniInt, MiniInt]", + ApplicativeTests[AppFunc[Option, MiniInt, ?]].applicative[MiniInt, MiniInt, MiniInt]) checkAll("Applicative[AppFunc[Option, Int, ?]]", SerializableTests.serializable(Applicative[AppFunc[Option, Int, ?]])) } diff --git a/tests/src/test/scala/cats/tests/FunctionSuite.scala b/tests/src/test/scala/cats/tests/FunctionSuite.scala index c1167cab94..e261826c6b 100644 --- a/tests/src/test/scala/cats/tests/FunctionSuite.scala +++ b/tests/src/test/scala/cats/tests/FunctionSuite.scala @@ -34,39 +34,41 @@ class FunctionSuite extends CatsSuite { checkAll("Function0[Int]", DeferTests[Function0].defer[Int]) checkAll("Defer[Function0[Int]]", SerializableTests.serializable(Defer[Function0])) - checkAll("Function1[Int, Int]", DeferTests[Function1[Int, ?]].defer[Int]) + checkAll("Function1[MiniInt, Int]", DeferTests[Function1[MiniInt, ?]].defer[Int]) checkAll("Defer[Function1[Int, Int]]", SerializableTests.serializable(Defer[Function1[Int, ?]])) checkAll("Function0[Int]", BimonadTests[Function0].bimonad[Int, Int, Int]) checkAll("Bimonad[Function0]", SerializableTests.serializable(Bimonad[Function0])) - implicit val iso = SemigroupalTests.Isomorphisms.invariant[Function1[Int, ?]] - checkAll("Function1[Int, Int]", SemigroupalTests[Function1[Int, ?]].semigroupal[Int, Int, Int]) + implicit val iso = SemigroupalTests.Isomorphisms.invariant[Function1[MiniInt, ?]] + checkAll("Function1[MiniInt, Int]", SemigroupalTests[Function1[MiniInt, ?]].semigroupal[Int, Int, Int]) // TODO: make an binary compatible way to do this //checkAll("Function1[Int => ?]", DeferTests[Function1[Int, ?]].defer[Int]) checkAll("Semigroupal[Function1[Int, ?]]", SerializableTests.serializable(Semigroupal[Function1[Int, ?]])) - checkAll("Function1[Int, Int]", MonadTests[Int => ?].monad[Int, Int, Int]) + checkAll("Function1[MiniInt, Int]", MonadTests[MiniInt => ?].monad[Int, Int, Int]) checkAll("Monad[Int => ?]", SerializableTests.serializable(Monad[Int => ?])) - checkAll("Function1[Int, Int]", CommutativeArrowTests[Function1].commutativeArrow[Int, Int, Int, Int, Int, Int]) + checkAll("Function1[MiniInt, MiniInt]", + CommutativeArrowTests[Function1].commutativeArrow[MiniInt, MiniInt, MiniInt, MiniInt, MiniInt, MiniInt]) checkAll("Arrow[Function1]", SerializableTests.serializable(CommutativeArrow[Function1])) - checkAll("Function1[Int, Int]", ChoiceTests[Function1].choice[Int, Int, Int, Int]) + checkAll("Function1", ChoiceTests[Function1].choice[MiniInt, Boolean, Int, Long]) checkAll("Choice[Function1]", SerializableTests.serializable(Choice[Function1])) - checkAll("Function1[Int, Int]", ArrowChoiceTests[Function1].arrowChoice[Int, Int, Int, Int, Int, Int]) + checkAll("Function1", ArrowChoiceTests[Function1].arrowChoice[MiniInt, MiniInt, MiniInt, MiniInt, MiniInt, MiniInt]) checkAll("ArrowChoice[Function1]", SerializableTests.serializable(ArrowChoice[Function1])) - checkAll("Function1[Int, Int]", ContravariantTests[? => Int].contravariant[Int, Int, Int]) + checkAll("Function1", ContravariantTests[? => MiniInt].contravariant[MiniInt, MiniInt, MiniInt]) checkAll("Contravariant[? => Int]", SerializableTests.serializable(Contravariant[? => Int])) - checkAll("Function1[Int, Int]", MonoidKTests[λ[α => α => α]].monoidK[Int]) + checkAll("Function1", MonoidKTests[λ[α => α => α]].monoidK[MiniInt]) checkAll("MonoidK[λ[α => α => α]", SerializableTests.serializable(catsStdMonoidKForFunction1)) - checkAll("Function1[Int, Int]", DistributiveTests[Int => ?].distributive[Int, Int, Int, Id, Function1[Int, ?]]) + checkAll("Function1[MiniInt, ?]", + DistributiveTests[MiniInt => ?].distributive[Int, Int, Int, Id, Function1[MiniInt, ?]]) checkAll("Distributive[Int => ?]", SerializableTests.serializable(Distributive[Int => ?])) // law checks for the various Function0-related instances @@ -92,8 +94,8 @@ class FunctionSuite extends CatsSuite { // Test for Arrow applicative Applicative[String => ?] - checkAll("Function1[String, ?]", - ApplicativeTests[Function1[String, ?]](Applicative.catsApplicativeForArrow[Function1, String]) + checkAll("Function1[MiniInt, ?]", + ApplicativeTests[Function1[MiniInt, ?]](Applicative.catsApplicativeForArrow[Function1, MiniInt]) .applicative[Int, Int, Int]) // serialization tests for the various Function0-related instances @@ -112,18 +114,19 @@ class FunctionSuite extends CatsSuite { checkAll("Function0", SerializableTests.serializable(Distributive[Function0])) // law checks for the various Function1-related instances - checkAll("Function1[String, Semi]", SemigroupTests[Function1[String, Semi]].semigroup) - checkAll("Function1[String, CSemi]", CommutativeSemigroupTests[Function1[String, CSemi]].commutativeSemigroup) - checkAll("Function1[String, Bnd]", BandTests[Function1[String, Bnd]].band) - checkAll("Function1[String, SL]", SemilatticeTests[Function1[String, SL]].semilattice) - checkAll("Function1[String, BSL]", BoundedSemilatticeTests[Function1[String, BSL]].boundedSemilattice) - checkAll("Function1[String, Mono]", MonoidTests[Function1[String, Mono]].monoid) - checkAll("Function1[String, CMono]", CommutativeMonoidTests[Function1[String, CMono]].commutativeMonoid) - checkAll("Function1[String, Grp]", GroupTests[Function1[String, Grp]].group) - checkAll("Function1[String, CGrp]", CommutativeGroupTests[Function1[String, CGrp]].commutativeGroup) + checkAll("Function1[MiniInt, Semi]", SemigroupTests[Function1[MiniInt, Semi]].semigroup) + checkAll("Function1[MiniInt, CSemi]", CommutativeSemigroupTests[Function1[MiniInt, CSemi]].commutativeSemigroup) + checkAll("Function1[MiniInt, Bnd]", BandTests[Function1[MiniInt, Bnd]].band) + checkAll("Function1[MiniInt, SL]", SemilatticeTests[Function1[MiniInt, SL]].semilattice) + checkAll("Function1[MiniInt, BSL]", BoundedSemilatticeTests[Function1[MiniInt, BSL]].boundedSemilattice) + checkAll("Function1[MiniInt, Mono]", MonoidTests[Function1[MiniInt, Mono]].monoid) + checkAll("Function1[MiniInt, CMono]", CommutativeMonoidTests[Function1[MiniInt, CMono]].commutativeMonoid) + checkAll("Function1[MiniInt, Grp]", GroupTests[Function1[MiniInt, Grp]].group) + checkAll("Function1[MiniInt, CGrp]", CommutativeGroupTests[Function1[MiniInt, CGrp]].commutativeGroup) // Isos for ContravariantMonoidal implicit val isoCodomain = SemigroupalTests.Isomorphisms.invariant[Function1[?, Long]] - checkAll("Function1[?, Monoid]", ContravariantMonoidalTests[Function1[?, Long]].contravariantMonoidal[Int, Int, Int]) + checkAll("Function1[?, Monoid]", + ContravariantMonoidalTests[Function1[?, Long]].contravariantMonoidal[MiniInt, MiniInt, MiniInt]) // serialization tests for the various Function1-related instances checkAll("Semigroup[String => Semi]", SerializableTests.serializable(Semigroup[String => Semi])) diff --git a/tests/src/test/scala/cats/tests/IndexedReaderWriterStateTSuite.scala b/tests/src/test/scala/cats/tests/IndexedReaderWriterStateTSuite.scala index d03fa4f278..b2d258ea05 100644 --- a/tests/src/test/scala/cats/tests/IndexedReaderWriterStateTSuite.scala +++ b/tests/src/test/scala/cats/tests/IndexedReaderWriterStateTSuite.scala @@ -52,13 +52,13 @@ class ReaderWriterStateTSuite extends CatsSuite { } test("ReaderWriterState.pure, ReaderWriterStateT.pure and IndexedReaderWriterStateT.pure are consistent") { - forAll { (value: Int) => + forAll { (context: String, value: Int) => val rws: ReaderWriterState[String, Vector[String], Int, Int] = ReaderWriterState.pure(value) val rwst: ReaderWriterState[String, Vector[String], Int, Int] = ReaderWriterStateT.pure(value) val irwst: ReaderWriterState[String, Vector[String], Int, Int] = IndexedReaderWriterStateT.pure(value) - rws should ===(rwst) - rwst should ===(irwst) + rws.run(context, value) should ===(rwst.run(context, value)) + rwst.run(context, value) should ===(irwst.run(context, value)) } } @@ -70,131 +70,131 @@ class ReaderWriterStateTSuite extends CatsSuite { } test("ReaderWriterState.get, ReaderWriterStateT.get and IndexedReaderWriterStateT.get are consistent") { - forAll { (initial: Int) => + forAll { (context: String, initial: Int) => val rws: ReaderWriterState[String, Vector[String], Int, Int] = ReaderWriterState.get val rwst: ReaderWriterState[String, Vector[String], Int, Int] = ReaderWriterStateT.get val irwst: ReaderWriterState[String, Vector[String], Int, Int] = IndexedReaderWriterStateT.get - rws should ===(rwst) - rwst should ===(irwst) + rws.run(context, initial) should ===(rwst.run(context, initial)) + rwst.run(context, initial) should ===(irwst.run(context, initial)) } } test("ReaderWriterState.get and instance get are consistent") { - forAll { (initial: Int) => + forAll { (context: String, initial: Int) => val singleton = ReaderWriterState.get[String, String, Int] val instance = ReaderWriterState.pure[String, String, Int, Unit](()).get - singleton should ===(instance) + singleton.run(context, initial) should ===(instance.run(context, initial)) } } test("ReaderWriterState.inspect and instance inspect are consistent") { - forAll { (initial: Int) => + forAll { (context: String, initial: Int) => val singleton = ReaderWriterState.inspect[String, String, Int, String](_.toString) val instance = ReaderWriterState.pure[String, String, Int, Unit](()).inspect(_.toString) - singleton should ===(instance) + singleton.run(context, initial) should ===(instance.run(context, initial)) } } test("ReaderWriterState.inspect, ReaderWriterStateT.inspect and IndexedReaderWriterStateT.inspect are consistent") { - forAll { (f: Int => Int) => + forAll { (context: String, initial: Int, f: Int => Int) => val rws: ReaderWriterState[String, Vector[String], Int, Int] = ReaderWriterState.inspect(f) val rwst: ReaderWriterState[String, Vector[String], Int, Int] = ReaderWriterStateT.inspect(f) val irwst: ReaderWriterState[String, Vector[String], Int, Int] = IndexedReaderWriterStateT.inspect(f) - rws should ===(rwst) - rwst should ===(irwst) + rws.run(context, initial) should ===(rwst.run(context, initial)) + rwst.run(context, initial) should ===(irwst.run(context, initial)) } } test("ReaderWriterState.inspect, ReaderWriterStateT.inspectF and IndexedReaderWriterStateT.inspectF are consistent") { - forAll { (f: Int => Int) => + forAll { (context: String, initial: Int, f: Int => Int) => val rws: ReaderWriterState[String, String, Int, Int] = ReaderWriterState.inspect(f) val rwst: ReaderWriterState[String, String, Int, Int] = ReaderWriterStateT.inspectF(f.andThen(Eval.now)) val irwst: ReaderWriterState[String, String, Int, Int] = IndexedReaderWriterStateT.inspectF(f.andThen(Eval.now)) - rws should ===(rwst) - rwst should ===(irwst) + rws.run(context, initial) should ===(rwst.run(context, initial)) + rwst.run(context, initial) should ===(irwst.run(context, initial)) } } test("ReaderWriterState.modify, ReaderWriterStateT.modify and IndexedReaderWriterStateT.modify are consistent") { - forAll { (f: Int => Int) => + forAll { (context: String, initial: Int, f: Int => Int) => val rws: ReaderWriterState[String, Vector[String], Int, Unit] = ReaderWriterState.modify(f) val rwst: ReaderWriterState[String, Vector[String], Int, Unit] = ReaderWriterStateT.modify(f) val irwst: ReaderWriterState[String, Vector[String], Int, Unit] = IndexedReaderWriterStateT.modify(f) - rws should ===(rwst) - rwst should ===(irwst) + rws.run(context, initial) should ===(rwst.run(context, initial)) + rwst.run(context, initial) should ===(irwst.run(context, initial)) } } test("ReaderWriterState.modify, ReaderWriterStateT.modifyF and IndexedReaderWriterStateT.modifyF are consistent") { - forAll { (f: Int => Int) => + forAll { (context: String, initial: Int, f: Int => Int) => val rws: ReaderWriterState[String, Vector[String], Int, Unit] = ReaderWriterState.modify(f) val rwst: ReaderWriterState[String, Vector[String], Int, Unit] = ReaderWriterStateT.modifyF(f.andThen(Eval.now)) val irwst: ReaderWriterState[String, Vector[String], Int, Unit] = IndexedReaderWriterStateT.modifyF(f.andThen(Eval.now)) - rws should ===(rwst) - rwst should ===(irwst) + rws.run(context, initial) should ===(rwst.run(context, initial)) + rwst.run(context, initial) should ===(irwst.run(context, initial)) } } test("ReaderWriterState.pure, ReaderWriterStateT.liftF and IndexedReaderWriterStateT.liftF are consistent") { - forAll { (value: Int) => + forAll { (context: String, initial: Int, value: Int) => val rws: ReaderWriterState[String, Vector[String], Int, Int] = ReaderWriterState.pure(value) val rwst: ReaderWriterState[String, Vector[String], Int, Int] = ReaderWriterStateT.liftF(Eval.now(value)) val irwst: ReaderWriterState[String, Vector[String], Int, Int] = IndexedReaderWriterStateT.liftF(Eval.now(value)) - rws should ===(rwst) - rwst should ===(irwst) + rws.run(context, initial) should ===(rwst.run(context, initial)) + rwst.run(context, initial) should ===(irwst.run(context, initial)) } } test("ReaderWriterState.set, ReaderWriterStateT.set and IndexedReaderWriterStateT.set are consistent") { - forAll { (next: Int) => + forAll { (context: String, initial: Int, next: Int) => val rws: ReaderWriterState[String, Vector[String], Int, Unit] = ReaderWriterState.set(next) val rwst: ReaderWriterState[String, Vector[String], Int, Unit] = ReaderWriterStateT.set(next) val irwst: ReaderWriterState[String, Vector[String], Int, Unit] = IndexedReaderWriterStateT.set(next) - rws should ===(rwst) - rwst should ===(irwst) + rws.run(context, initial) should ===(rwst.run(context, initial)) + rwst.run(context, initial) should ===(irwst.run(context, initial)) } } test("ReaderWriterState.set, ReaderWriterStateT.setF and IndexedReaderWriterStateT.setF are consistent") { - forAll { (next: Int) => + forAll { (context: String, initial: Int, next: Int) => val rws: ReaderWriterState[String, Vector[String], Int, Unit] = ReaderWriterState.set(next) val rwst: ReaderWriterState[String, Vector[String], Int, Unit] = ReaderWriterStateT.setF(Eval.now(next)) val irwst: ReaderWriterState[String, Vector[String], Int, Unit] = IndexedReaderWriterStateT.setF(Eval.now(next)) - rws should ===(rwst) - rwst should ===(irwst) + rws.run(context, initial) should ===(rwst.run(context, initial)) + rwst.run(context, initial) should ===(irwst.run(context, initial)) } } test("ReaderWriterState.tell, ReaderWriterStateT.tell and IndexedReaderWriterStateT.tell are consistent") { - forAll { (log: String) => + forAll { (context: String, initial: Int, log: String) => val rws: ReaderWriterState[String, String, Int, Unit] = ReaderWriterState.tell(log) val rwst: ReaderWriterState[String, String, Int, Unit] = ReaderWriterStateT.tell(log) val irwst: ReaderWriterState[String, String, Int, Unit] = IndexedReaderWriterStateT.tell(log) - rws should ===(rwst) - rwst should ===(irwst) + rws.run(context, initial) should ===(rwst.run(context, initial)) + rwst.run(context, initial) should ===(irwst.run(context, initial)) } } test("ReaderWriterState.tell, ReaderWriterStateT.tellF and IndexedReaderWriterStateT.tellF are consistent") { - forAll { (log: String) => + forAll { (context: String, initial: Int, log: String) => val rws: ReaderWriterState[String, String, Int, Unit] = ReaderWriterState.tell(log) val rwst: ReaderWriterState[String, String, Int, Unit] = ReaderWriterStateT.tellF(Eval.now(log)) val irwst: ReaderWriterState[String, String, Int, Unit] = IndexedReaderWriterStateT.tellF(Eval.now(log)) - rws should ===(rwst) - rwst should ===(irwst) + rws.run(context, initial) should ===(rwst.run(context, initial)) + rwst.run(context, initial) should ===(irwst.run(context, initial)) } } @@ -236,7 +236,7 @@ class ReaderWriterStateTSuite extends CatsSuite { test("reset on pure is a noop") { forAll { (c: String, s: Int, a: Int) => val pure = ReaderWriterState.pure[String, String, Int, Int](a) - pure.reset should ===(pure) + pure.reset.run(c, s) should ===(pure.run(c, s)) } } @@ -316,15 +316,17 @@ class ReaderWriterStateTSuite extends CatsSuite { IndexedReaderWriterStateT.catsDataFunctorForIRWST(ListWrapper.functor) ) - checkAll("IndexedReaderWriterStateT[Eval, String, String, Int, String, ?]", - DeferTests[IndexedReaderWriterStateT[Eval, String, String, Int, String, ?]].defer[Int]) + checkAll( + "IndexedReaderWriterStateT[Eval, Boolean, String, MiniInt, String, ?]", + DeferTests[IndexedReaderWriterStateT[Eval, Boolean, String, MiniInt, String, ?]].defer[Int] + ) { implicit val F: Monad[ListWrapper] = ListWrapper.monad checkAll( - "IndexedReaderWriterStateT[ListWrapper, String, String, Int, String, Int]", - FunctorTests[IndexedReaderWriterStateT[ListWrapper, String, String, Int, String, ?]].functor[Int, Int, Int] + "IndexedReaderWriterStateT[ListWrapper, Boolean, String, MiniInt, String, ?]", + FunctorTests[IndexedReaderWriterStateT[ListWrapper, Boolean, String, MiniInt, String, ?]].functor[Int, Int, Int] ) checkAll( "Functor[IndexedReaderWriterStateT[ListWrapper, String, String, Int, String, ?]]", @@ -332,9 +334,9 @@ class ReaderWriterStateTSuite extends CatsSuite { ) checkAll( - "IndexedReaderWriterStateT[ListWrapper, String, String, String, Int, Int]", - ContravariantTests[IndexedReaderWriterStateT[ListWrapper, String, String, ?, Int, Int]] - .contravariant[String, String, String] + "IndexedReaderWriterStateT[ListWrapper, String, String, ?, Int, Int]", + ContravariantTests[IndexedReaderWriterStateT[ListWrapper, Boolean, String, ?, Int, Int]] + .contravariant[MiniInt, String, Boolean] ) checkAll( "Contravariant[IndexedReaderWriterStateT[ListWrapper, String, String, ?, Int, Int]]", @@ -342,9 +344,9 @@ class ReaderWriterStateTSuite extends CatsSuite { ) checkAll( - "IndexedReaderWriterStateT[ListWrapper, String, String, Int, String, Int]", - ProfunctorTests[IndexedReaderWriterStateT[ListWrapper, String, String, ?, ?, Int]] - .profunctor[Int, Int, Int, String, String, String] + "IndexedReaderWriterStateT[ListWrapper, String, String, ?, ?, Int]", + ProfunctorTests[IndexedReaderWriterStateT[ListWrapper, Boolean, String, ?, ?, Int]] + .profunctor[MiniInt, Int, Int, String, String, String] ) checkAll( "Profunctor[IndexedReaderWriterStateT[ListWrapper, String, String, ?, ?, Int]]", @@ -352,9 +354,9 @@ class ReaderWriterStateTSuite extends CatsSuite { ) checkAll( - "IndexedReaderWriterStateT[ListWrapper, String, String, Int, String, Int]", - StrongTests[IndexedReaderWriterStateT[ListWrapper, String, String, ?, ?, Int]] - .strong[Int, Int, Int, String, String, String] + "IndexedReaderWriterStateT[ListWrapper, Boolean, String, ?, ?, Int]", + StrongTests[IndexedReaderWriterStateT[ListWrapper, Boolean, String, ?, ?, Int]] + .strong[MiniInt, Int, Boolean, Boolean, Boolean, String] ) checkAll( "Strong[IndexedReaderWriterStateT[ListWrapper, String, String, ?, ?, Int]]", @@ -362,9 +364,9 @@ class ReaderWriterStateTSuite extends CatsSuite { ) checkAll( - "IndexedReaderWriterStateT[ListWrapper, String, String, Int, Int, String]", - BifunctorTests[IndexedReaderWriterStateT[ListWrapper, String, String, Int, ?, ?]] - .bifunctor[Int, Int, Int, String, String, String] + "IndexedReaderWriterStateT[ListWrapper, String, String, Int, ?, ?]", + BifunctorTests[IndexedReaderWriterStateT[ListWrapper, Boolean, String, MiniInt, ?, ?]] + .bifunctor[Int, Int, Boolean, String, String, String] ) checkAll( "Bifunctor[IndexedReaderWriterStateT[ListWrapper, String, String, Int, ?, ?]]", @@ -375,13 +377,13 @@ class ReaderWriterStateTSuite extends CatsSuite { { implicit val G: Monad[ListWrapper] = ListWrapper.monad - val SA = IRWST.catsDataAlternativeForIRWST[ListWrapper, String, String, Int](ListWrapper.monad, - ListWrapper.alternative, - Monoid[String]) + val SA = IRWST.catsDataAlternativeForIRWST[ListWrapper, Boolean, String, MiniInt](ListWrapper.monad, + ListWrapper.alternative, + Monoid[String]) checkAll( - "IndexedReaderWriterStateT[ListWrapper, String, String, Int, Int, Int]", - AlternativeTests[IRWST[ListWrapper, String, String, Int, Int, ?]](SA).alternative[Int, Int, Int] + "IndexedReaderWriterStateT[ListWrapper, String, String, Int, Int, ?]", + AlternativeTests[IRWST[ListWrapper, Boolean, String, MiniInt, MiniInt, ?]](SA).alternative[Int, Int, Int] ) checkAll("Alternative[IndexedReaderWriterStateT[ListWrapper, String, String, Int, Int, ?]]", SerializableTests.serializable(SA)) @@ -390,8 +392,10 @@ class ReaderWriterStateTSuite extends CatsSuite { { implicit val LWM: Monad[ListWrapper] = ListWrapper.monad - checkAll("ReaderWriterStateT[ListWrapper, String, String, Int, Int]", - MonadTests[ReaderWriterStateT[ListWrapper, String, String, Int, ?]].monad[Int, Int, Int]) + checkAll( + "ReaderWriterStateT[ListWrapper, Boolean, String, MiniInt, MiniInt, ?]", + MonadTests[ReaderWriterStateT[ListWrapper, Boolean, String, MiniInt, ?]].monad[Int, Int, Int] + ) checkAll( "Monad[ReaderWriterStateT[ListWrapper, String, String, Int, ?]]", SerializableTests.serializable(Monad[ReaderWriterStateT[ListWrapper, String, String, Int, ?]]) @@ -399,12 +403,14 @@ class ReaderWriterStateTSuite extends CatsSuite { } { - implicit val iso = SemigroupalTests.Isomorphisms.invariant[ReaderWriterStateT[Option, String, String, Int, ?]] - implicit val eqEitherTFA: Eq[EitherT[ReaderWriterStateT[Option, String, String, Int, ?], Unit, Int]] = - EitherT.catsDataEqForEitherT[ReaderWriterStateT[Option, String, String, Int, ?], Unit, Int] + implicit val iso = SemigroupalTests.Isomorphisms.invariant[ReaderWriterStateT[Option, Boolean, String, MiniInt, ?]] + implicit val eqEitherTFA: Eq[EitherT[ReaderWriterStateT[Option, Boolean, String, MiniInt, ?], Unit, Int]] = + EitherT.catsDataEqForEitherT[ReaderWriterStateT[Option, Boolean, String, MiniInt, ?], Unit, Int] - checkAll("ReaderWriterStateT[Option, String, String, Int, Int]", - MonadErrorTests[ReaderWriterStateT[Option, String, String, Int, ?], Unit].monadError[Int, Int, Int]) + checkAll( + "ReaderWriterStateT[Option, Boolean, String, MiniIntInt, ?]", + MonadErrorTests[ReaderWriterStateT[Option, Boolean, String, MiniInt, ?], Unit].monadError[Int, Int, Int] + ) checkAll( "MonadError[ReaderWriterStateT[Option, String, String, Int, ?], Unit]", SerializableTests.serializable(MonadError[ReaderWriterStateT[Option, String, String, Int, ?], Unit]) @@ -415,8 +421,10 @@ class ReaderWriterStateTSuite extends CatsSuite { implicit val F: Monad[ListWrapper] = ListWrapper.monad implicit val S: SemigroupK[ListWrapper] = ListWrapper.semigroupK - checkAll("ReaderWriterStateT[ListWrapper, String, String, Int, Int]", - SemigroupKTests[ReaderWriterStateT[ListWrapper, String, String, Int, ?]].semigroupK[Int]) + checkAll( + "ReaderWriterStateT[ListWrapper, Boolean, String, MiniInt, ?]", + SemigroupKTests[ReaderWriterStateT[ListWrapper, Boolean, String, MiniInt, ?]].semigroupK[Int] + ) checkAll( "SemigroupK[ReaderWriterStateT[ListWrapper, String, String, Int, ?]]", SerializableTests.serializable(SemigroupK[ReaderWriterStateT[ListWrapper, String, String, Int, ?]]) @@ -442,9 +450,9 @@ object ReaderWriterStateTSuite { } } - implicit def IRWSTEq[F[_], E, L, SA, SB, A](implicit SA: Arbitrary[SA], + implicit def IRWSTEq[F[_], E, L, SA, SB, A](implicit SA: ExhaustiveCheck[SA], SB: Arbitrary[SB], - E: Arbitrary[E], + E: ExhaustiveCheck[E], FLSB: Eq[F[(L, SB, A)]], F: Monad[F]): Eq[IndexedReaderWriterStateT[F, E, L, SA, SB, A]] = Eq.by[IndexedReaderWriterStateT[F, E, L, SA, SB, A], (E, SA) => F[(L, SB, A)]] { state => (e, s) => diff --git a/tests/src/test/scala/cats/tests/IndexedStateTSuite.scala b/tests/src/test/scala/cats/tests/IndexedStateTSuite.scala index a26b4f4f4c..801ef01990 100644 --- a/tests/src/test/scala/cats/tests/IndexedStateTSuite.scala +++ b/tests/src/test/scala/cats/tests/IndexedStateTSuite.scala @@ -9,7 +9,6 @@ import cats.kernel.instances.tuple._ import cats.laws.discipline._ import cats.laws.discipline.eq._ import cats.laws.discipline.arbitrary._ -import org.scalacheck.Arbitrary class IndexedStateTSuite extends CatsSuite { @@ -166,7 +165,7 @@ class IndexedStateTSuite extends CatsSuite { } test("flatMap and flatMapF consistent") { - forAll { (stateT: StateT[Option, Long, Int], f: Int => Option[Int]) => + forAll { (stateT: StateT[Option, MiniInt, Int], f: Int => Option[Int]) => stateT.flatMap(a => StateT(s => f(a).map(b => (s, b)))) should ===(stateT.flatMapF(f)) } } @@ -178,7 +177,7 @@ class IndexedStateTSuite extends CatsSuite { } test("modify identity is a noop") { - forAll { (f: StateT[List, Long, Int]) => + forAll { (f: StateT[List, MiniInt, Int]) => f.modify(identity) should ===(f) } } @@ -196,9 +195,9 @@ class IndexedStateTSuite extends CatsSuite { } test("State.modify equivalent to get then set") { - forAll { (f: Long => Long) => + forAll { (f: MiniInt => MiniInt) => val s1 = for { - l <- State.get[Long] + l <- State.get[MiniInt] _ <- State.set(f(l)) } yield () @@ -232,14 +231,14 @@ class IndexedStateTSuite extends CatsSuite { } test(".get equivalent to flatMap with State.get") { - forAll { (s: State[Long, Int]) => + forAll { (s: State[MiniInt, Int]) => s.get should ===(s.flatMap(_ => State.get)) } } test("StateT#transformS with identity is identity") { - forAll { (s: StateT[List, Long, Int]) => - s.transformS[Long](identity, (s, i) => i) should ===(s) + forAll { (s: StateT[List, MiniInt, Int]) => + s.transformS[MiniInt](identity, (s, i) => i) should ===(s) } } @@ -342,15 +341,15 @@ class IndexedStateTSuite extends CatsSuite { Profunctor[IndexedStateT[ListWrapper, ?, ?, String]] } - checkAll("IndexedStateT[Eval, String, String, ?]", DeferTests[IndexedStateT[Eval, String, String, ?]].defer[Int]) + checkAll("IndexedStateT[Eval, MiniInt, String, ?]", DeferTests[IndexedStateT[Eval, MiniInt, String, ?]].defer[Int]) { // F needs a Monad to do Eq on StateT implicit val F: Monad[ListWrapper] = ListWrapper.monad implicit val FS: Functor[IndexedStateT[ListWrapper, String, Int, ?]] = IndexedStateT.catsDataFunctorForIndexedStateT - checkAll("IndexedStateT[ListWrapper, String, Int, Int]", - FunctorTests[IndexedStateT[ListWrapper, String, Int, ?]].functor[Int, Int, Int]) + checkAll("IndexedStateT[ListWrapper, MiniInt, Int, Int]", + FunctorTests[IndexedStateT[ListWrapper, MiniInt, Int, ?]].functor[Int, Int, Int]) checkAll("Functor[IndexedStateT[ListWrapper, Int, ?]]", SerializableTests.serializable(Functor[IndexedStateT[ListWrapper, String, Int, ?]])) @@ -361,10 +360,10 @@ class IndexedStateTSuite extends CatsSuite { implicit val F0 = ListWrapper.monad implicit val FF = ListWrapper.functorFilter - checkAll("IndexedStateT[ListWrapper, String, Int, ?]", - FunctorFilterTests[IndexedStateT[ListWrapper, String, Int, ?]].functorFilter[Int, Int, Int]) - checkAll("FunctorFilter[IndexedStateT[ListWrapper, String, Int, ?]]", - SerializableTests.serializable(FunctorFilter[IndexedStateT[ListWrapper, String, Int, ?]])) + checkAll("IndexedStateT[ListWrapper, MiniInt, Int, ?]", + FunctorFilterTests[IndexedStateT[ListWrapper, MiniInt, Int, ?]].functorFilter[Int, Int, Int]) + checkAll("FunctorFilter[IndexedStateT[ListWrapper, MiniInt, Int, ?]]", + SerializableTests.serializable(FunctorFilter[IndexedStateT[ListWrapper, MiniInt, Int, ?]])) FunctorFilter[IndexedStateT[ListWrapper, String, Int, ?]] } @@ -374,8 +373,8 @@ class IndexedStateTSuite extends CatsSuite { implicit val FS: Contravariant[IndexedStateT[ListWrapper, ?, Int, Int]] = IndexedStateT.catsDataContravariantForIndexedStateT - checkAll("IndexedStateT[ListWrapper, Int, Int, Int]", - ContravariantTests[IndexedStateT[ListWrapper, ?, Int, Int]].contravariant[Int, Int, Int]) + checkAll("IndexedStateT[ListWrapper, ?, Int, Boolean]", + ContravariantTests[IndexedStateT[ListWrapper, ?, Int, Int]].contravariant[MiniInt, Int, Boolean]) checkAll("Contravariant[IndexedStateT[ListWrapper, ?, Int, Int]]", SerializableTests.serializable(Contravariant[IndexedStateT[ListWrapper, ?, Int, Int]])) @@ -386,8 +385,8 @@ class IndexedStateTSuite extends CatsSuite { implicit val F: Monad[ListWrapper] = ListWrapper.monad implicit val FS: Bifunctor[IndexedStateT[ListWrapper, Int, ?, ?]] = IndexedStateT.catsDataBifunctorForIndexedStateT - checkAll("IndexedStateT[ListWrapper, Int, String, Int]", - BifunctorTests[IndexedStateT[ListWrapper, Int, ?, ?]].bifunctor[String, String, String, Int, Int, Int]) + checkAll("IndexedStateT[ListWrapper, MiniInt, String, Int]", + BifunctorTests[IndexedStateT[ListWrapper, MiniInt, ?, ?]].bifunctor[String, String, String, Int, Int, Int]) checkAll("Bifunctor[IndexedStateT[ListWrapper, Int, ?, ?]]", SerializableTests.serializable(Bifunctor[IndexedStateT[ListWrapper, Int, ?, ?]])) @@ -400,7 +399,7 @@ class IndexedStateTSuite extends CatsSuite { IndexedStateT.catsDataProfunctorForIndexedStateT checkAll("IndexedStateT[ListWrapper, String, Int, Int]", - ProfunctorTests[IndexedStateT[ListWrapper, ?, ?, Int]].profunctor[String, String, String, Int, Int, Int]) + ProfunctorTests[IndexedStateT[ListWrapper, ?, ?, Int]].profunctor[MiniInt, String, String, Int, Int, Int]) checkAll("Profunctor[IndexedStateT[ListWrapper, ?, ?, Int]]", SerializableTests.serializable(Profunctor[IndexedStateT[ListWrapper, ?, ?, Int]])) @@ -411,8 +410,8 @@ class IndexedStateTSuite extends CatsSuite { implicit val F: Monad[ListWrapper] = ListWrapper.monad implicit val FS: Strong[IndexedStateT[ListWrapper, ?, ?, Int]] = IndexedStateT.catsDataStrongForIndexedStateT - checkAll("IndexedStateT[ListWrapper, String, Int, Int]", - StrongTests[IndexedStateT[ListWrapper, ?, ?, Int]].strong[String, String, String, Int, Int, Int]) + checkAll("IndexedStateT[ListWrapper, ?, ?, Int]", + StrongTests[IndexedStateT[ListWrapper, ?, ?, Int]].strong[MiniInt, Int, Boolean, Boolean, Boolean, String]) checkAll("Strong[IndexedStateT[ListWrapper, ?, ?, Int]]", SerializableTests.serializable(Strong[IndexedStateT[ListWrapper, ?, ?, Int]])) @@ -423,9 +422,9 @@ class IndexedStateTSuite extends CatsSuite { // F has a Monad implicit val F = ListWrapper.monad - checkAll("IndexedStateT[ListWrapper, Int, Int]", - MonadTests[IndexedStateT[ListWrapper, Int, Int, ?]].monad[Int, Int, Int]) - checkAll("Monad[StateT[ListWrapper, Int, ?]]", + checkAll("IndexedStateT[ListWrapper, MiniInt, Int, ?]", + MonadTests[IndexedStateT[ListWrapper, MiniInt, MiniInt, ?]].monad[Int, Int, Int]) + checkAll("Monad[IndexedStateT[ListWrapper, Int, Int, ?]]", SerializableTests.serializable(Monad[IndexedStateT[ListWrapper, Int, Int, ?]])) Monad[IndexedStateT[ListWrapper, Int, Int, ?]] @@ -440,8 +439,8 @@ class IndexedStateTSuite extends CatsSuite { implicit val F = ListWrapper.monad implicit val S = ListWrapper.semigroupK - checkAll("IndexedStateT[ListWrapper, Int, Int]", - SemigroupKTests[IndexedStateT[ListWrapper, Int, Int, ?]].semigroupK[Int]) + checkAll("IndexedStateT[ListWrapper, MiniInt, Int, ?]", + SemigroupKTests[IndexedStateT[ListWrapper, MiniInt, Int, ?]].semigroupK[Int]) checkAll("SemigroupK[IndexedStateT[ListWrapper, Int, ?]]", SerializableTests.serializable(SemigroupK[IndexedStateT[ListWrapper, String, Int, ?]])) } @@ -451,10 +450,11 @@ class IndexedStateTSuite extends CatsSuite { implicit val G = ListWrapper.monad implicit val F = ListWrapper.alternative val SA = - IndexedStateT.catsDataAlternativeForIndexedStateT[ListWrapper, Int](ListWrapper.monad, ListWrapper.alternative) + IndexedStateT + .catsDataAlternativeForIndexedStateT[ListWrapper, MiniInt](ListWrapper.monad, ListWrapper.alternative) - checkAll("IndexedStateT[ListWrapper, Int, Int, Int]", - AlternativeTests[IndexedStateT[ListWrapper, Int, Int, ?]](SA).alternative[Int, Int, Int]) + checkAll("IndexedStateT[ListWrapper, MiniInt, Int, Int]", + AlternativeTests[IndexedStateT[ListWrapper, MiniInt, MiniInt, ?]](SA).alternative[Int, Int, Int]) checkAll("Alternative[IndexedStateT[ListWrapper, Int, Int, ?]]", SerializableTests.serializable(SA)) Monad[IndexedStateT[ListWrapper, Int, Int, ?]] @@ -468,19 +468,20 @@ class IndexedStateTSuite extends CatsSuite { } { - implicit val iso = SemigroupalTests.Isomorphisms.invariant[State[Long, ?]] + implicit val iso = SemigroupalTests.Isomorphisms.invariant[State[MiniInt, ?]] - checkAll("State[Long, ?]", MonadTests[State[Long, ?]].monad[Int, Int, Int]) + checkAll("State[MiniInt, ?]", MonadTests[State[MiniInt, ?]].monad[Int, Int, Int]) checkAll("Monad[State[Long, ?]]", SerializableTests.serializable(Monad[State[Long, ?]])) } { // F has a MonadError - implicit val iso = SemigroupalTests.Isomorphisms.invariant[StateT[Option, Int, ?]] - implicit val eqEitherTFA: Eq[EitherT[StateT[Option, Int, ?], Unit, Int]] = - EitherT.catsDataEqForEitherT[StateT[Option, Int, ?], Unit, Int] + implicit val iso = SemigroupalTests.Isomorphisms.invariant[StateT[Option, MiniInt, ?]] + implicit val eqEitherTFA: Eq[EitherT[StateT[Option, MiniInt, ?], Unit, Int]] = + EitherT.catsDataEqForEitherT[StateT[Option, MiniInt, ?], Unit, Int] - checkAll("StateT[Option, Int, Int]", MonadErrorTests[StateT[Option, Int, ?], Unit].monadError[Int, Int, Int]) + checkAll("StateT[Option, MiniInt, Int]", + MonadErrorTests[StateT[Option, MiniInt, ?], Unit].monadError[Int, Int, Int]) checkAll("MonadError[StateT[Option, Int, ?], Unit]", SerializableTests.serializable(MonadError[StateT[Option, Int, ?], Unit])) } @@ -488,7 +489,7 @@ class IndexedStateTSuite extends CatsSuite { } object IndexedStateTSuite extends IndexedStateTSuiteInstances { - implicit def stateEq[S: Eq: Arbitrary, A: Eq]: Eq[State[S, A]] = + implicit def stateEq[S: Eq: ExhaustiveCheck, A: Eq]: Eq[State[S, A]] = indexedStateTEq[Eval, S, S, A] val add1: State[Int, Int] = State(n => (n + 1, n)) @@ -496,7 +497,7 @@ object IndexedStateTSuite extends IndexedStateTSuiteInstances { sealed trait IndexedStateTSuiteInstances { - implicit def indexedStateTEq[F[_], SA, SB, A](implicit SA: Arbitrary[SA], + implicit def indexedStateTEq[F[_], SA, SB, A](implicit SA: ExhaustiveCheck[SA], FSB: Eq[F[(SB, A)]], F: FlatMap[F]): Eq[IndexedStateT[F, SA, SB, A]] = Eq.by[IndexedStateT[F, SA, SB, A], SA => F[(SB, A)]](state => s => state.run(s)) diff --git a/tests/src/test/scala/cats/tests/KernelContravariantSuite.scala b/tests/src/test/scala/cats/tests/KernelContravariantSuite.scala index 0619e7d5d2..420bb4116e 100644 --- a/tests/src/test/scala/cats/tests/KernelContravariantSuite.scala +++ b/tests/src/test/scala/cats/tests/KernelContravariantSuite.scala @@ -10,27 +10,27 @@ class KernelContravariantSuite extends CatsSuite { Contravariant[Eq] Semigroupal[Eq] ContravariantSemigroupal[Eq] - checkAll("Contravariant[Eq]", ContravariantTests[Eq].contravariant[Int, Int, Int]) - checkAll("Semigroupal[Eq]", SemigroupalTests[Eq].semigroupal[Int, Int, Int]) + checkAll("Contravariant[Eq]", ContravariantTests[Eq].contravariant[MiniInt, Int, Boolean]) + checkAll("Semigroupal[Eq]", SemigroupalTests[Eq].semigroupal[MiniInt, Boolean, Boolean]) checkAll("Contravariant[Eq]", SerializableTests.serializable(Contravariant[Eq])) Invariant[PartialOrder] Contravariant[PartialOrder] Semigroupal[PartialOrder] ContravariantSemigroupal[PartialOrder] - checkAll("Contravariant[PartialOrder]", ContravariantTests[PartialOrder].contravariant[Int, Int, Int]) - checkAll("Semigroupal[PartialOrder]", SemigroupalTests[PartialOrder].semigroupal[Int, Int, Int]) + checkAll("Contravariant[PartialOrder]", ContravariantTests[PartialOrder].contravariant[MiniInt, Int, Boolean]) + checkAll("Semigroupal[PartialOrder]", SemigroupalTests[PartialOrder].semigroupal[MiniInt, Boolean, Boolean]) checkAll("Contravariant[PartialOrder]", SerializableTests.serializable(Contravariant[PartialOrder])) Invariant[Order] Contravariant[Order] Semigroupal[Order] ContravariantSemigroupal[Order] - checkAll("Contravariant[Order]", ContravariantTests[Order].contravariant[Int, Int, Int]) - checkAll("Semigroupal[Order]", SemigroupalTests[Order].semigroupal[Int, Int, Int]) + checkAll("Contravariant[Order]", ContravariantTests[Order].contravariant[MiniInt, Int, Boolean]) + checkAll("Semigroupal[Order]", SemigroupalTests[Order].semigroupal[MiniInt, Boolean, Boolean]) checkAll("Contravariant[Order]", SerializableTests.serializable(Contravariant[Order])) Contravariant[Hash] - checkAll("Contravariant[Hash]", ContravariantTests[Hash].contravariant[Int, Int, Int]) + checkAll("Contravariant[Hash]", ContravariantTests[Hash].contravariant[MiniInt, Int, Boolean]) checkAll("Contravariant[Hash]", SerializableTests.serializable(Contravariant[Hash])) } diff --git a/tests/src/test/scala/cats/tests/KleisliSuite.scala b/tests/src/test/scala/cats/tests/KleisliSuite.scala index f2f79300b4..b5c4965b84 100644 --- a/tests/src/test/scala/cats/tests/KleisliSuite.scala +++ b/tests/src/test/scala/cats/tests/KleisliSuite.scala @@ -7,197 +7,148 @@ import cats.data.{Const, EitherT, Kleisli, Reader, ReaderT} import cats.laws.discipline._ import cats.laws.discipline.arbitrary._ import cats.laws.discipline.eq._ -import org.scalacheck.Arbitrary import cats.kernel.laws.discipline.{MonoidTests, SemigroupTests} import cats.laws.discipline.{DeferTests, MonoidKTests, SemigroupKTests} import Helpers.CSemi import catalysts.Platform class KleisliSuite extends CatsSuite { - implicit def kleisliEq[F[_], A, B](implicit A: Arbitrary[A], FB: Eq[F[B]]): Eq[Kleisli[F, A, B]] = + implicit def kleisliEq[F[_], A, B](implicit ev: Eq[A => F[B]]): Eq[Kleisli[F, A, B]] = Eq.by[Kleisli[F, A, B], A => F[B]](_.run) - implicit def readerEq[A, B](implicit A: Arbitrary[A], FB: Eq[Id[B]]): Eq[Reader[A, B]] = + implicit def readerEq[A, B](implicit ev: Eq[A => B]): Eq[Reader[A, B]] = kleisliEq - implicit val eitherTEq = EitherT.catsDataEqForEitherT[Kleisli[Option, Int, ?], Unit, Int] - implicit val eitherTEq2 = EitherT.catsDataEqForEitherT[Reader[Int, ?], Unit, Int] + implicit val eitherTEq = EitherT.catsDataEqForEitherT[Kleisli[Option, MiniInt, ?], Unit, Int] + implicit val eitherTEq2 = EitherT.catsDataEqForEitherT[Reader[MiniInt, ?], Unit, Int] implicit val iso = SemigroupalTests.Isomorphisms.invariant[Kleisli[Option, Int, ?]] implicit val iso2 = SemigroupalTests.Isomorphisms.invariant[Reader[Int, ?]] { - implicit val instance: ApplicativeError[Kleisli[Option, Int, ?], Unit] = - Kleisli.catsDataApplicativeErrorForKleisli[Option, Unit, Int](cats.instances.option.catsStdInstancesForOption) - checkAll("Kleisli[Option, Int, Int] with Unit", - ApplicativeErrorTests[Kleisli[Option, Int, ?], Unit](instance).applicativeError[Int, Int, Int]) + implicit val instance: ApplicativeError[Kleisli[Option, MiniInt, ?], Unit] = + Kleisli.catsDataApplicativeErrorForKleisli[Option, Unit, MiniInt](cats.instances.option.catsStdInstancesForOption) + checkAll("Kleisli[Option, MinInt, ?] with Unit", + ApplicativeErrorTests[Kleisli[Option, MiniInt, ?], Unit](instance).applicativeError[Int, Int, Int]) checkAll("ApplicativeError[Kleisli[Option, Int, Int], Unit]", SerializableTests.serializable(instance)) } - checkAll("Kleisli[Eval, Int, ?]", DeferTests[Kleisli[Eval, Int, ?]].defer[Int]) - checkAll("Kleisli[Option, Int, Int] with Unit", - MonadErrorTests[Kleisli[Option, Int, ?], Unit].monadError[Int, Int, Int]) + checkAll("Kleisli[Eval, MiniInt, ?]", DeferTests[Kleisli[Eval, MiniInt, ?]].defer[Int]) + checkAll("Kleisli[Option, MiniInt, ?] with Unit", + MonadErrorTests[Kleisli[Option, MiniInt, ?], Unit].monadError[Int, Int, Int]) checkAll("MonadError[Kleisli[Option, Int, Int], Unit]", SerializableTests.serializable(MonadError[Kleisli[Option, Int, ?], Unit])) - checkAll("Kleisli[Option, Int, Int]", SemigroupalTests[Kleisli[Option, Int, ?]].semigroupal[Int, Int, Int]) + checkAll("Kleisli[Option, MiniInt, ?]", SemigroupalTests[Kleisli[Option, MiniInt, ?]].semigroupal[Int, Int, Int]) checkAll("Semigroupal[Kleisli[Option, Int, ?]]", SerializableTests.serializable(Semigroupal[Kleisli[Option, Int, ?]])) - checkAll("Kleisli[(CSemi, ?), Int, ?]", - CommutativeFlatMapTests[Kleisli[(CSemi, ?), Int, ?]].commutativeFlatMap[Int, Int, Int]) + checkAll("Kleisli[(CSemi, ?), MiniInt, ?]", + CommutativeFlatMapTests[Kleisli[(CSemi, ?), MiniInt, ?]].commutativeFlatMap[Int, Int, Int]) checkAll("CommutativeFlatMap[Kleisli[(CSemi, ?), Int, ?]]", SerializableTests.serializable(CommutativeFlatMap[Kleisli[(CSemi, ?), Int, ?]])) - checkAll("Kleisli[Option, Int, ?]", CommutativeMonadTests[Kleisli[Option, Int, ?]].commutativeMonad[Int, Int, Int]) + checkAll("Kleisli[Option, MiniInt, ?]", + CommutativeMonadTests[Kleisli[Option, MiniInt, ?]].commutativeMonad[Int, Int, Int]) checkAll("CommutativeMonad[Kleisli[Option, Int, ?]]", SerializableTests.serializable(CommutativeMonad[Kleisli[Option, Int, ?]])) - checkAll("Kleisli[Id, Int, ?]", CommutativeMonadTests[Kleisli[Id, Int, ?]].commutativeMonad[Int, Int, Int]) + checkAll("Kleisli[Id, MiniInt, ?]", CommutativeMonadTests[Kleisli[Id, MiniInt, ?]].commutativeMonad[Int, Int, Int]) checkAll("CommutativeMonad[Kleisli[Id, Int, ?]]", SerializableTests.serializable(CommutativeMonad[Kleisli[Id, Int, ?]])) - { - implicit val catsDataArrowForKleisli = Kleisli.catsDataArrowChoiceForKleisli[List] - checkAll("Kleisli[List, Int, Int]", ArrowTests[Kleisli[List, ?, ?]].arrow[Int, Int, Int, Int, Int, Int]) - checkAll("Arrow[Kleisli[List, ?, ?]]", SerializableTests.serializable(Arrow[Kleisli[List, ?, ?]])) - } + checkAll("Kleisli[List, ?, ?]", + ArrowTests[Kleisli[List, ?, ?]].arrow[MiniInt, MiniInt, MiniInt, MiniInt, MiniInt, Boolean]) + checkAll("Arrow[Kleisli[List, ?, ?]]", SerializableTests.serializable(Arrow[Kleisli[List, ?, ?]])) - { - implicit val catsDataArrowChoiceForKleisli = Kleisli.catsDataArrowChoiceForKleisli[List] - checkAll("Kleisli[List, Int, Int]", ArrowChoiceTests[Kleisli[List, ?, ?]].arrowChoice[Int, Int, Int, Int, Int, Int]) - checkAll("ArrowChoice[Kleisli[List, ?, ?]]", SerializableTests.serializable(ArrowChoice[Kleisli[List, ?, ?]])) - } + checkAll("Kleisli[List, ?, ?]", + ArrowChoiceTests[Kleisli[List, ?, ?]].arrowChoice[MiniInt, MiniInt, MiniInt, MiniInt, MiniInt, Boolean]) + checkAll("ArrowChoice[Kleisli[List, ?, ?]]", SerializableTests.serializable(ArrowChoice[Kleisli[List, ?, ?]])) - { - implicit val catsDataCommutativeArrowForKleisli = Kleisli.catsDataCommutativeArrowForKleisli[Option] - checkAll("Kleisli[Option, Int, Int]", - CommutativeArrowTests[Kleisli[Option, ?, ?]].commutativeArrow[Int, Int, Int, Int, Int, Int]) - checkAll("CommutativeArrow[Kleisli[Option, ?, ?]]", - SerializableTests.serializable(CommutativeArrow[Kleisli[Option, ?, ?]])) - } + checkAll("Kleisli[Option, Int, Int]", + CommutativeArrowTests[Kleisli[Option, ?, ?]] + .commutativeArrow[MiniInt, MiniInt, MiniInt, MiniInt, MiniInt, Boolean]) + checkAll("CommutativeArrow[Kleisli[Option, ?, ?]]", + SerializableTests.serializable(CommutativeArrow[Kleisli[Option, ?, ?]])) - { - implicit val catsDataChoiceForKleisli = Kleisli.catsDataChoiceForKleisli[Option] - checkAll("Kleisli[Option, Int, Int]", ChoiceTests[Kleisli[Option, ?, ?]].choice[Int, Int, Int, Int]) - checkAll("Choice[Kleisli[Option, ?, ?]]", SerializableTests.serializable(Choice[Kleisli[Option, ?, ?]])) - } + checkAll("Kleisli[Option, ?, ?]", ChoiceTests[Kleisli[Option, ?, ?]].choice[MiniInt, Boolean, Int, Int]) + checkAll("Choice[Kleisli[Option, ?, ?]]", SerializableTests.serializable(Choice[Kleisli[Option, ?, ?]])) - { - implicit val catsDataMonadForKleisli = Kleisli.catsDataMonadForKleisli[Option, Int] - checkAll("Kleisli[Option, Int, Int]", MonadTests[Kleisli[Option, Int, ?]].monad[Int, Int, Int]) - checkAll("Monad[Kleisli[Option, ?, ?], Int]", SerializableTests.serializable(Monad[Kleisli[Option, Int, ?]])) - } + checkAll("Kleisli[Option, MiniInt, ?]", MonadTests[Kleisli[Option, MiniInt, ?]].monad[Int, Int, Int]) + checkAll("Monad[Kleisli[Option, ?, ?], Int]", SerializableTests.serializable(Monad[Kleisli[Option, Int, ?]])) - { - implicit val catsDataMonadForReader = Kleisli.catsDataMonadForKleisliId[Int] - checkAll("Reader[Int, Int]", MonadTests[Reader[Int, ?]].monad[Int, Int, Int]) - checkAll("Monad[Reader[?, ?], Int]", SerializableTests.serializable(Monad[Reader[Int, ?]])) - } + checkAll("Reader[MiniInt, ?]", MonadTests[Reader[MiniInt, ?]].monad[Int, Int, Int]) + checkAll("Monad[Reader[?, ?], Int]", SerializableTests.serializable(Monad[Reader[Int, ?]])) - { - implicit val catsDataStrongForKleisli = Kleisli.catsDataStrongForKleisli[Option] - checkAll("Kleisli[Option, Int, Int]", StrongTests[Kleisli[Option, ?, ?]].strong[Int, Int, Int, Int, Int, Int]) - checkAll("Strong[Kleisli[Option, ?, ?]]", SerializableTests.serializable(Strong[Kleisli[Option, ?, ?]])) - } + checkAll("Kleisli[Option, ?, ?]", + StrongTests[Kleisli[Option, ?, ?]].strong[MiniInt, Boolean, Boolean, Boolean, Boolean, Int]) + checkAll("Strong[Kleisli[Option, ?, ?]]", SerializableTests.serializable(Strong[Kleisli[Option, ?, ?]])) - { - implicit val catsDataFlatMapForKleisli = Kleisli.catsDataFlatMapForKleisli[Option, Int] - checkAll("Kleisli[Option, Int, Int]", FlatMapTests[Kleisli[Option, Int, ?]].flatMap[Int, Int, Int]) - checkAll("FlatMap[Kleisli[Option, Int, ?]]", SerializableTests.serializable(FlatMap[Kleisli[Option, Int, ?]])) - } + checkAll("Kleisli[Option, MiniInt, Int]", FlatMapTests[Kleisli[Option, MiniInt, ?]].flatMap[Int, Int, Int]) + checkAll("FlatMap[Kleisli[Option, Int, ?]]", SerializableTests.serializable(FlatMap[Kleisli[Option, Int, ?]])) - { - implicit val catsDataAlternativeForKleisli = Kleisli.catsDataAlternativeForKleisli[Option, Int] - checkAll("Kleisli[Option, Int, Int]", AlternativeTests[Kleisli[Option, Int, ?]].alternative[Int, Int, Int]) - checkAll("Alternative[Kleisli[Option, Int, ?]]", - SerializableTests.serializable(Alternative[Kleisli[Option, Int, ?]])) - } + checkAll("Kleisli[Option, MiniInt, ?]", AlternativeTests[Kleisli[Option, MiniInt, ?]].alternative[Int, Int, Int]) + checkAll("Alternative[Kleisli[Option, Int, ?]]", SerializableTests.serializable(Alternative[Kleisli[Option, Int, ?]])) - { - implicit val catsDataContravariantMonoidalForKleisli = - Kleisli.catsDataContravariantMonoidalForKleisli[Const[String, ?], Int] - checkAll("Kleisli[Const[String, ?], Int, Int]", - ContravariantMonoidalTests[Kleisli[Const[String, ?], Int, ?]].contravariantMonoidal[Int, Int, Int]) - checkAll("ContravariantMonoidal[Kleisli[Option, Int, ?]]", - SerializableTests.serializable(ContravariantMonoidal[Kleisli[Const[String, ?], Int, ?]])) - } + checkAll("Kleisli[Const[String, ?], MiniInt, ?]", + ContravariantMonoidalTests[Kleisli[Const[String, ?], MiniInt, ?]].contravariantMonoidal[Int, Int, Int]) + checkAll("ContravariantMonoidal[Kleisli[Option, Int, ?]]", + SerializableTests.serializable(ContravariantMonoidal[Kleisli[Const[String, ?], Int, ?]])) - { - implicit val catsDataApplicativeForKleisli = Kleisli.catsDataApplicativeForKleisli[Option, Int] - checkAll("Kleisli[Option, Int, Int]", ApplicativeTests[Kleisli[Option, Int, ?]].applicative[Int, Int, Int]) - checkAll("Applicative[Kleisli[Option, Int, ?]]", - SerializableTests.serializable(Applicative[Kleisli[Option, Int, ?]])) - } + checkAll("Kleisli[Option, MiniInt, Int]", ApplicativeTests[Kleisli[Option, MiniInt, ?]].applicative[Int, Int, Int]) + checkAll("Applicative[Kleisli[Option, Int, ?]]", SerializableTests.serializable(Applicative[Kleisli[Option, Int, ?]])) - { - implicit val catsDataApplyForKleisli = Kleisli.catsDataApplyForKleisli[Option, Int] - checkAll("Kleisli[Option, Int, Int]", ApplyTests[Kleisli[Option, Int, ?]].apply[Int, Int, Int]) - checkAll("Apply[Kleisli[Option, Int, ?]]", SerializableTests.serializable(Apply[Kleisli[Option, Int, ?]])) - } + checkAll("Kleisli[Option, MiniInt, Int]", ApplyTests[Kleisli[Option, MiniInt, ?]].apply[Int, Int, Int]) + checkAll("Apply[Kleisli[Option, Int, ?]]", SerializableTests.serializable(Apply[Kleisli[Option, Int, ?]])) - { - implicit val catsDataFunctorForKleisli = Kleisli.catsDataFunctorForKleisli[Option, Int] - checkAll("Kleisli[Option, Int, Int]", FunctorTests[Kleisli[Option, Int, ?]].functor[Int, Int, Int]) - checkAll("Functor[Kleisli[Option, Int, ?]]", SerializableTests.serializable(Functor[Kleisli[Option, Int, ?]])) - } + checkAll("Kleisli[Option, MiniInt, Int]", FunctorTests[Kleisli[Option, MiniInt, ?]].functor[Int, Int, Int]) + checkAll("Functor[Kleisli[Option, Int, ?]]", SerializableTests.serializable(Functor[Kleisli[Option, Int, ?]])) { implicit val FF = ListWrapper.functorFilter - checkAll("Kleisli[ListWrapper, Int, ?]", - FunctorFilterTests[Kleisli[ListWrapper, Int, ?]].functorFilter[Int, Int, Int]) - checkAll("FunctorFilter[Kleisli[ListWrapper, Int, ?]]", - SerializableTests.serializable(FunctorFilter[Kleisli[ListWrapper, Int, ?]])) + checkAll("Kleisli[ListWrapper, MiniInt, ?]", + FunctorFilterTests[Kleisli[ListWrapper, MiniInt, ?]].functorFilter[Int, Int, Int]) + checkAll("FunctorFilter[Kleisli[ListWrapper, MiniInt, ?]]", + SerializableTests.serializable(FunctorFilter[Kleisli[ListWrapper, MiniInt, ?]])) FunctorFilter[ReaderT[ListWrapper, Int, ?]] } - { - checkAll("Kleisli[Function0, Int, ?]", - DistributiveTests[Kleisli[Function0, Int, ?]].distributive[Int, Int, Int, Option, Id]) - checkAll("Distributive[Kleisli[Function0, Int, ?]]", - SerializableTests.serializable(Distributive[Kleisli[Function0, Int, ?]])) - } + checkAll("Kleisli[Function0, MiniInt, ?]", + DistributiveTests[Kleisli[Function0, MiniInt, ?]].distributive[Int, Int, Int, Option, Id]) + checkAll("Distributive[Kleisli[Function0, Int, ?]]", + SerializableTests.serializable(Distributive[Kleisli[Function0, Int, ?]])) - { - implicit val catsDataMonoidForKleisli = Kleisli.catsDataMonoidForKleisli[Option, Int, String] - checkAll("Kleisli[Option, Int, String]", MonoidTests[Kleisli[Option, Int, String]].monoid) - checkAll("Monoid[Kleisli[Option, Int, String]]", SerializableTests.serializable(catsDataMonoidForKleisli)) - } + checkAll("Kleisli[Option, MiniInt, String]", MonoidTests[Kleisli[Option, MiniInt, String]].monoid) + checkAll("Monoid[Kleisli[Option, Int, String]]", SerializableTests.serializable(Monoid[Kleisli[Option, Int, String]])) - { - implicit val catsDataSemigroupForKleisli = Kleisli.catsDataSemigroupForKleisli[Option, Int, String] - checkAll("Kleisli[Option, Int, String]", SemigroupTests[Kleisli[Option, Int, String]].semigroup) - checkAll("Semigroup[Kleisli[Option, Int, String]]", SerializableTests.serializable(catsDataSemigroupForKleisli)) - } + checkAll("Kleisli[Option, MiniInt, String]", SemigroupTests[Kleisli[Option, MiniInt, String]].semigroup) + checkAll("Semigroup[Kleisli[Option, Int, String]]", + SerializableTests.serializable(Semigroup[Kleisli[Option, Int, String]])) { implicit val catsDataMonoidKForKleisli = Kleisli.endoMonoidK[Option] - checkAll("Kleisli[Option, Int, Int]", MonoidKTests[λ[α => Kleisli[Option, α, α]]].monoidK[Int]) + checkAll("Kleisli[Option, MiniInt, MiniInt]", MonoidKTests[λ[α => Kleisli[Option, α, α]]].monoidK[MiniInt]) checkAll("MonoidK[λ[α => Kleisli[Option, α, α]]]", SerializableTests.serializable(catsDataMonoidKForKleisli)) } { implicit val catsDataSemigroupKForKleisli = Kleisli.endoSemigroupK[Option] - checkAll("Kleisli[Option, Int, Int]", SemigroupKTests[λ[α => Kleisli[Option, α, α]]].semigroupK[Int]) - checkAll("SemigroupK[λ[α => Kleisli[Option, α, α]]]", SerializableTests.serializable(catsDataSemigroupKForKleisli)) + checkAll("Kleisli[Option, MiniInt, MiniInt]", SemigroupKTests[λ[α => Kleisli[Option, α, α]]].semigroupK[MiniInt]) + checkAll("SemigroupK[λ[α => Kleisli[Option, α, α]]]", + SerializableTests.serializable(SemigroupK[λ[α => Kleisli[Option, α, α]]])) } - { - implicit val semigroupk = Kleisli.catsDataSemigroupKForKleisli[Option, String] - checkAll("Kleisli[Option, String, Int]", SemigroupKTests[Kleisli[Option, String, ?]].semigroupK[Int]) - checkAll("SemigroupK[Kleisli[Option, String, ?]]", SerializableTests.serializable(semigroupk)) - } + checkAll("Kleisli[Option, MiniInt, Int]", SemigroupKTests[Kleisli[Option, MiniInt, ?]].semigroupK[Int]) + checkAll("SemigroupK[Kleisli[Option, String, ?]]", + SerializableTests.serializable(SemigroupK[Kleisli[Option, String, ?]])) - { - implicit val monoidk = Kleisli.catsDataMonoidKForKleisli[Option, String] - checkAll("Kleisli[Option, String, Int]", MonoidKTests[Kleisli[Option, String, ?]].monoidK[Int]) - checkAll("MonoidK[Kleisli[Option, String, ?]]", SerializableTests.serializable(monoidk)) - } + checkAll("Kleisli[Option, MiniInt, ?]", MonoidKTests[Kleisli[Option, MiniInt, ?]].monoidK[Int]) + checkAll("MonoidK[Kleisli[Option, String, ?]]", SerializableTests.serializable(MonoidK[Kleisli[Option, String, ?]])) - checkAll("Reader[Int, Int]", FunctorTests[Reader[Int, ?]].functor[Int, Int, Int]) + checkAll("Reader[MiniInt, Int]", FunctorTests[Reader[MiniInt, ?]].functor[Int, Int, Int]) - checkAll("Kleisli[Option, ?, Int]", ContravariantTests[Kleisli[Option, ?, Int]].contravariant[Int, Int, Int]) + checkAll("Kleisli[Option, ?, Int]", ContravariantTests[Kleisli[Option, ?, Int]].contravariant[MiniInt, Int, Boolean]) checkAll("Contravariant[Kleisli[Option, ?, Int]]", SerializableTests.serializable(Contravariant[Kleisli[Option, ?, Int]])) diff --git a/tests/src/test/scala/cats/tests/MiniIntSuite.scala b/tests/src/test/scala/cats/tests/MiniIntSuite.scala new file mode 100644 index 0000000000..a63d690931 --- /dev/null +++ b/tests/src/test/scala/cats/tests/MiniIntSuite.scala @@ -0,0 +1,48 @@ +package cats +package tests + +import cats.laws.discipline.MiniInt +import MiniInt._ +import cats.laws.discipline.arbitrary._ +import cats.kernel.{BoundedSemilattice, CommutativeGroup, CommutativeMonoid} +import cats.kernel.laws.discipline._ + +import org.scalacheck.Gen + +class MiniIntSuite extends CatsSuite { + checkAll("MiniInt", OrderTests[MiniInt].order) + checkAll("Order[MiniInt]", SerializableTests.serializable(Order[MiniInt])) + + checkAll("MiniInt", HashTests[MiniInt].hash) + checkAll("Hash[MiniInt]", SerializableTests.serializable(Hash[MiniInt])) + + { + implicit val g: CommutativeGroup[MiniInt] = miniIntAddition + checkAll("MiniInt addition", CommutativeGroupTests[MiniInt].commutativeGroup) + checkAll("CommutativeGroup[MiniInt] addition", SerializableTests.serializable(miniIntAddition)) + } + + { + implicit val m: CommutativeMonoid[MiniInt] = miniIntMultiplication + checkAll("MiniInt addition", CommutativeMonoidTests[MiniInt].commutativeMonoid) + checkAll("CommutativeMonoid[MiniInt] multiplication", SerializableTests.serializable(miniIntMultiplication)) + } + + { + implicit val b: BoundedSemilattice[MiniInt] = miniIntOr + checkAll("MiniInt |", BoundedSemilatticeTests[MiniInt].boundedSemilattice) + checkAll("BoundedSemilattice[MiniInt] |", SerializableTests.serializable(miniIntOr)) + } + + test("int roundtrip") { + forAll { i: MiniInt => + MiniInt.fromInt(i.toInt) should ===(Some(i)) + } + } + + test("int bounds") { + forAll(Gen.chooseNum(MiniInt.minIntValue, MiniInt.maxIntValue)) { i: Int => + MiniInt.fromInt(i).map(_.toInt) should ===(Some(i)) + } + } +} diff --git a/tests/src/test/scala/cats/tests/NestedSuite.scala b/tests/src/test/scala/cats/tests/NestedSuite.scala index a35c423072..5864f1e3e1 100644 --- a/tests/src/test/scala/cats/tests/NestedSuite.scala +++ b/tests/src/test/scala/cats/tests/NestedSuite.scala @@ -7,7 +7,7 @@ import cats.data._ import cats.laws.discipline._ import cats.laws.discipline.SemigroupalTests.Isomorphisms._ import cats.laws.discipline.arbitrary._ -import cats.laws.discipline.eq.catsLawsEqForShow +import cats.laws.discipline.eq._ class NestedSuite extends CatsSuite { // we have a lot of generated lists of lists in these tests. We have to tell @@ -59,8 +59,8 @@ class NestedSuite extends CatsSuite { { // Invariant + Contravariant = Invariant val instance = Nested.catsDataInvariantForNestedContravariant(ListWrapper.invariant, Contravariant[Show]) - checkAll("Nested[ListWrapper, Show]", - InvariantTests[Nested[ListWrapper, Show, ?]](instance).invariant[Int, Int, Int]) + checkAll("Nested[ListWrapper, Show, ?]", + InvariantTests[Nested[ListWrapper, Show, ?]](instance).invariant[MiniInt, Int, Boolean]) checkAll("Invariant[Nested[ListWrapper, Show, ?]]", SerializableTests.serializable(instance)) } @@ -74,7 +74,8 @@ class NestedSuite extends CatsSuite { { // Covariant + contravariant functor composition - checkAll("Nested[Option, Show, ?]", ContravariantTests[Nested[Option, Show, ?]].contravariant[Int, Int, Int]) + checkAll("Nested[Option, Show, ?]", + ContravariantTests[Nested[Option, Show, ?]].contravariant[MiniInt, Int, Boolean]) checkAll("Contravariant[Nested[Option, Show, ?]]", SerializableTests.serializable(Contravariant[Nested[Option, Show, ?]])) } @@ -106,7 +107,8 @@ class NestedSuite extends CatsSuite { { // Contravariant + Functor = Contravariant - checkAll("Nested[Show, Option, ?]", ContravariantTests[Nested[Show, Option, ?]].contravariant[Int, Int, Int]) + checkAll("Nested[Show, Option, ?]", + ContravariantTests[Nested[Show, Option, ?]].contravariant[MiniInt, Int, Boolean]) checkAll("Contravariant[Nested[Show, Option, ?]]", SerializableTests.serializable(Contravariant[Nested[Show, Option, ?]])) } @@ -223,8 +225,10 @@ class NestedSuite extends CatsSuite { { import cats.laws.discipline.eq._ //Distributive composition - checkAll("Nested[Function1[Int, ?], Function0, ?]", - DistributiveTests[Nested[Function1[Int, ?], Function0, ?]].distributive[Int, Int, Int, Option, Function0]) + checkAll( + "Nested[Function1[MiniInt, ?], Function0, ?]", + DistributiveTests[Nested[Function1[MiniInt, ?], Function0, ?]].distributive[Int, Int, Int, Option, Function0] + ) checkAll("Distributive[Nested[Function1[Int,?], Function0, ?]]", SerializableTests.serializable(Distributive[Nested[Function1[Int, ?], Function0, ?]])) } diff --git a/tests/src/test/scala/cats/tests/OpSuite.scala b/tests/src/test/scala/cats/tests/OpSuite.scala index 0b2e4ed358..6766ae1911 100644 --- a/tests/src/test/scala/cats/tests/OpSuite.scala +++ b/tests/src/test/scala/cats/tests/OpSuite.scala @@ -10,14 +10,14 @@ import cats.kernel.laws.discipline.EqTests class OpSuite extends CatsSuite { { - implicit val catsKernelEqForOp = Op.catsKernelEqForOp[Function1, Char, Int] - checkAll("Op[Function1, Char, Int]", EqTests[Op[Function1, Char, Int]].eqv) - checkAll("Eq[Op[Function1, Char, Int]]", SerializableTests.serializable(Eq[Op[Function1, Char, Int]])) + implicit val catsKernelEqForOp = Op.catsKernelEqForOp[Function1, Int, MiniInt] + checkAll("Op[Function1, Int, MiniInt]", EqTests[Op[Function1, Int, MiniInt]].eqv) + checkAll("Eq[Op[Function1, Int, MiniInt]]", SerializableTests.serializable(Eq[Op[Function1, Int, MiniInt]])) } { implicit val catsDataCategoryForOp = Op.catsDataCategoryForOp[Function1] - checkAll("Op[Function1, Char, Int]", CategoryTests[Op[Function1, ?, ?]].category[Char, Int, Char, Int]) + checkAll("Op[Function1, ?, ?]", CategoryTests[Op[Function1, ?, ?]].category[Char, MiniInt, Char, Boolean]) checkAll("Category[Op[Function1, ?, ?]]", SerializableTests.serializable(Category[Op[Function1, ?, ?]])) } @@ -28,7 +28,7 @@ class OpSuite extends CatsSuite { // Arr is Function1 Category[Op[Function1, ?, ?]] Compose[Op[Function1, ?, ?]] - Eq[Op[Function1, Char, Int]] + Eq[Op[Function1, Char, MiniInt]] // Arr is Kleisli[Option, ?, ?] Category[Op[Kleisli[Option, ?, ?], ?, ?]] diff --git a/tests/src/test/scala/cats/tests/OptionTSuite.scala b/tests/src/test/scala/cats/tests/OptionTSuite.scala index 6edb9ef5d2..2a4173ad32 100644 --- a/tests/src/test/scala/cats/tests/OptionTSuite.scala +++ b/tests/src/test/scala/cats/tests/OptionTSuite.scala @@ -85,7 +85,7 @@ class OptionTSuite extends CatsSuite { Contravariant[Show] Contravariant[OptionT[Show, ?]] - checkAll("OptionT[Show, ?]", ContravariantTests[OptionT[Show, ?]].contravariant[Int, Int, Int]) + checkAll("OptionT[Show, ?]", ContravariantTests[OptionT[Show, ?]].contravariant[MiniInt, Int, Boolean]) checkAll("Contravariant[OptionT[Show, ?]]", SerializableTests.serializable(Contravariant[OptionT[Show, ?]])) } diff --git a/tests/src/test/scala/cats/tests/OptionWrapper.scala b/tests/src/test/scala/cats/tests/OptionWrapper.scala new file mode 100644 index 0000000000..540890007f --- /dev/null +++ b/tests/src/test/scala/cats/tests/OptionWrapper.scala @@ -0,0 +1,29 @@ +package cats +package tests + +import cats.laws.discipline.ExhaustiveCheck + +import org.scalacheck.{Arbitrary, Cogen}, Arbitrary.arbitrary + +/** + * Similar to [[ListWrapper]], but using `Option` instead of `List` limits the size of the structure, which can be + * useful for limiting the space of test values to generate. + */ +final case class OptionWrapper[A](option: Option[A]) extends AnyVal + +object OptionWrapper { + val functor: Functor[OptionWrapper] = new Functor[OptionWrapper] { + def map[A, B](fa: OptionWrapper[A])(f: A => B) = OptionWrapper(fa.option.map(f)) + } + + implicit def optionWrapperArbitrary[A: Arbitrary]: Arbitrary[OptionWrapper[A]] = + Arbitrary(arbitrary[Option[A]].map(OptionWrapper.apply)) + + implicit def optionWrapperCogen[A: Cogen]: Cogen[OptionWrapper[A]] = + Cogen[Option[A]].contramap(_.option) + + implicit def catsLawsExhaustiveCheckForOptionWrapper[A]( + implicit A: ExhaustiveCheck[A] + ): ExhaustiveCheck[OptionWrapper[A]] = + ExhaustiveCheck.instance(ExhaustiveCheck[Option[A]].allValues.map(OptionWrapper(_))) +} diff --git a/tests/src/test/scala/cats/tests/OrderSuite.scala b/tests/src/test/scala/cats/tests/OrderSuite.scala index 44f4e3c925..7da7b97024 100644 --- a/tests/src/test/scala/cats/tests/OrderSuite.scala +++ b/tests/src/test/scala/cats/tests/OrderSuite.scala @@ -3,7 +3,7 @@ package tests import Helpers.Ord import cats.kernel.laws.discipline.{OrderTests, SerializableTests} -import cats.laws.discipline.ContravariantMonoidalTests +import cats.laws.discipline.{ContravariantMonoidalTests, MiniInt} import cats.laws.discipline.arbitrary._ import cats.laws.discipline.eq._ @@ -19,7 +19,7 @@ class OrderSuite extends CatsSuite { checkAll("Float", OrderTests[Float].order) checkAll("Long", OrderTests[Long].order) - checkAll("Order", ContravariantMonoidalTests[Order].contravariantMonoidal[Int, Int, Int]) + checkAll("Order", ContravariantMonoidalTests[Order].contravariantMonoidal[MiniInt, Boolean, Boolean]) checkAll("ContravariantMonoidal[Order]", SerializableTests.serializable(ContravariantMonoidal[Order])) test("order ops syntax") { diff --git a/tests/src/test/scala/cats/tests/OrderingSuite.scala b/tests/src/test/scala/cats/tests/OrderingSuite.scala index 1996e01b64..5298040f80 100644 --- a/tests/src/test/scala/cats/tests/OrderingSuite.scala +++ b/tests/src/test/scala/cats/tests/OrderingSuite.scala @@ -13,8 +13,9 @@ class OrderingSuite extends CatsSuite { ContravariantSemigroupal[Ordering] ContravariantMonoidal[Ordering] - checkAll("Contravariant[Ordering]", ContravariantTests[Ordering].contravariant[Int, Int, Int]) - checkAll("Semigroupal[Ordering]", SemigroupalTests[Ordering].semigroupal[Int, Int, Int]) - checkAll("ContravariantMonoidal[Ordering]", ContravariantMonoidalTests[Ordering].contravariantMonoidal[Int, Int, Int]) + checkAll("Contravariant[Ordering]", ContravariantTests[Ordering].contravariant[MiniInt, Int, Boolean]) + checkAll("Semigroupal[Ordering]", SemigroupalTests[Ordering].semigroupal[MiniInt, Boolean, Boolean]) + checkAll("ContravariantMonoidal[Ordering]", + ContravariantMonoidalTests[Ordering].contravariantMonoidal[MiniInt, Boolean, Boolean]) checkAll("ContravariantMonoidal[Ordering]", SerializableTests.serializable(ContravariantMonoidal[Ordering])) } diff --git a/tests/src/test/scala/cats/tests/ParallelSuite.scala b/tests/src/test/scala/cats/tests/ParallelSuite.scala index f99728ac68..bdb7a8593e 100644 --- a/tests/src/test/scala/cats/tests/ParallelSuite.scala +++ b/tests/src/test/scala/cats/tests/ParallelSuite.scala @@ -6,10 +6,9 @@ import cats.data.NonEmptyList.ZipNonEmptyList import cats.data.NonEmptyVector.ZipNonEmptyVector import cats.data._ import org.scalatest.FunSuite -import cats.laws.discipline.{ApplicativeErrorTests, NonEmptyParallelTests, ParallelTests, SerializableTests} +import cats.laws.discipline.{ApplicativeErrorTests, MiniInt, NonEmptyParallelTests, ParallelTests, SerializableTests} import cats.laws.discipline.eq._ import cats.laws.discipline.arbitrary._ -import org.scalacheck.Arbitrary import org.typelevel.discipline.scalatest.Discipline import scala.collection.immutable.SortedSet @@ -353,12 +352,13 @@ class ParallelSuite extends CatsSuite with ApplicativeErrorForEitherTest { SerializableTests.serializable(Parallel[Either[String, ?], Validated[String, ?]])) { - implicit def kleisliEq[F[_], A, B](implicit A: Arbitrary[A], FB: Eq[F[B]]): Eq[Kleisli[F, A, B]] = + implicit def kleisliEq[F[_], A, B](implicit ev: Eq[A => F[B]]): Eq[Kleisli[F, A, B]] = Eq.by[Kleisli[F, A, B], A => F[B]](_.run) checkAll( - "Parallel[KlesliT[M, ?], Nested[F, Option, ?]]", - ParallelTests[Kleisli[Either[String, ?], Int, ?], Kleisli[Validated[String, ?], Int, ?]].parallel[Int, String] + "Parallel[KlesliT[M, A, ?], Kleisli[F, A, ?]]", + ParallelTests[Kleisli[Either[String, ?], MiniInt, ?], Kleisli[Validated[String, ?], MiniInt, ?]] + .parallel[Int, String] ) } diff --git a/tests/src/test/scala/cats/tests/PartialOrderSuite.scala b/tests/src/test/scala/cats/tests/PartialOrderSuite.scala index a2b5fdf730..4b8d8e4359 100644 --- a/tests/src/test/scala/cats/tests/PartialOrderSuite.scala +++ b/tests/src/test/scala/cats/tests/PartialOrderSuite.scala @@ -3,7 +3,7 @@ package tests import Helpers.POrd import cats.kernel.laws.discipline.SerializableTests -import cats.laws.discipline.ContravariantMonoidalTests +import cats.laws.discipline.{ContravariantMonoidalTests, MiniInt} import org.scalatest.Assertion import cats.laws.discipline.arbitrary._ import cats.laws.discipline.eq._ @@ -22,7 +22,7 @@ class PartialOrderSuite extends CatsSuite { Contravariant[PartialOrder] } - checkAll("PartialOrder[Int]", ContravariantMonoidalTests[PartialOrder].contravariantMonoidal[Int, Int, Int]) + checkAll("PartialOrder", ContravariantMonoidalTests[PartialOrder].contravariantMonoidal[MiniInt, Boolean, Boolean]) checkAll("ContravariantMonoidal[PartialOrder]", SerializableTests.serializable(ContravariantMonoidal[PartialOrder])) test("companion object syntax") { diff --git a/tests/src/test/scala/cats/tests/PartialOrderingSuite.scala b/tests/src/test/scala/cats/tests/PartialOrderingSuite.scala index 631f297537..fa5f3a9991 100644 --- a/tests/src/test/scala/cats/tests/PartialOrderingSuite.scala +++ b/tests/src/test/scala/cats/tests/PartialOrderingSuite.scala @@ -12,11 +12,12 @@ class PartialOrderingSuite extends CatsSuite { Semigroupal[PartialOrdering] ContravariantSemigroupal[PartialOrdering] - checkAll("Contravariant[PartialOrdering]", ContravariantTests[PartialOrdering].contravariant[Int, Int, Int]) - checkAll("Semigroupal[PartialOrdering]", SemigroupalTests[PartialOrdering].semigroupal[Int, Int, Int]) + checkAll("Contravariant[PartialOrdering]", ContravariantTests[PartialOrdering].contravariant[MiniInt, Int, Boolean]) + checkAll("Semigroupal[PartialOrdering]", SemigroupalTests[PartialOrdering].semigroupal[MiniInt, Boolean, Boolean]) checkAll("Contravariant[PartialOrdering]", SerializableTests.serializable(Contravariant[PartialOrdering])) - checkAll("PartialOrdering[Int]", ContravariantMonoidalTests[PartialOrdering].contravariantMonoidal[Int, Int, Int]) + checkAll("PartialOrdering[Int]", + ContravariantMonoidalTests[PartialOrdering].contravariantMonoidal[MiniInt, Boolean, Boolean]) checkAll("ContravariantMonoidal[PartialOrdering]", SerializableTests.serializable(ContravariantMonoidal[PartialOrdering])) } diff --git a/tests/src/test/scala/cats/tests/RepresentableSuite.scala b/tests/src/test/scala/cats/tests/RepresentableSuite.scala index c29196f13b..c114c2e006 100644 --- a/tests/src/test/scala/cats/tests/RepresentableSuite.scala +++ b/tests/src/test/scala/cats/tests/RepresentableSuite.scala @@ -3,7 +3,7 @@ package cats.tests import cats.laws.discipline.SemigroupalTests.Isomorphisms import cats.laws.discipline.arbitrary._ import cats.laws.discipline.eq._ -import cats.laws.discipline.{BimonadTests, MonadTests, RepresentableTests, SerializableTests} +import cats.laws.discipline.{BimonadTests, MiniInt, MonadTests, RepresentableTests, SerializableTests} import cats.{Bimonad, Eq, Eval, Id, Representable} import org.scalacheck.Arbitrary import cats.data.Kleisli @@ -15,7 +15,7 @@ class RepresentableSuite extends CatsSuite { checkAll("Id[String] <-> Unit => String", RepresentableTests[Id, Unit].representable[String]) checkAll("Representable[Id]", SerializableTests.serializable(Representable[Id])) - checkAll("String => Int <-> String => Int", RepresentableTests[String => ?, String].representable[Int]) + checkAll("MiniInt => Int <-> MiniInt => Int", RepresentableTests[MiniInt => ?, MiniInt].representable[Int]) checkAll("Representable[String => ?]", SerializableTests.serializable(Representable[String => ?])) checkAll("Pair[String, String] <-> Boolean => String", RepresentableTests[Pair, Boolean].representable[String]) @@ -25,26 +25,26 @@ class RepresentableSuite extends CatsSuite { checkAll("Representable[Eval]", SerializableTests.serializable(Representable[Eval])) { - implicit val representableKleisliPair = Kleisli.catsDataRepresentableForKleisli[Pair, Boolean, String] + implicit val representableKleisliPair = Kleisli.catsDataRepresentableForKleisli[Pair, Boolean, MiniInt] - implicit def kleisliEq[F[_], A, B](implicit A: Arbitrary[A], FB: Eq[F[B]]): Eq[Kleisli[F, A, B]] = + implicit def kleisliEq[F[_], A, B](implicit ev: Eq[A => F[B]]): Eq[Kleisli[F, A, B]] = Eq.by[Kleisli[F, A, B], A => F[B]](_.run) checkAll( - "Kleisli[Pair, String, Int] <-> (String, Boolean) => Int", + "Kleisli[Pair, MiniInt, Int] <-> (MiniInt, Boolean) => Int", // Have to summon all implicits using 'implicitly' otherwise we get a diverging implicits error - RepresentableTests[Kleisli[Pair, String, ?], (String, Boolean)].representable[Int]( + RepresentableTests[Kleisli[Pair, MiniInt, ?], (MiniInt, Boolean)].representable[Int]( implicitly[Arbitrary[Int]], - implicitly[Arbitrary[Kleisli[Pair, String, Int]]], - implicitly[Arbitrary[(String, Boolean)]], - implicitly[Arbitrary[((String, Boolean)) => Int]], - implicitly[Eq[Kleisli[Pair, String, Int]]], + implicitly[Arbitrary[Kleisli[Pair, MiniInt, Int]]], + implicitly[Arbitrary[(MiniInt, Boolean)]], + implicitly[Arbitrary[((MiniInt, Boolean)) => Int]], + implicitly[Eq[Kleisli[Pair, MiniInt, Int]]], implicitly[Eq[Int]] ) ) - checkAll("Representable[Kleisli[Pair, String, ?]]", - SerializableTests.serializable(Representable[Kleisli[Pair, String, ?]])) + checkAll("Representable[Kleisli[Pair, MiniInt, ?]]", + SerializableTests.serializable(Representable[Kleisli[Pair, MiniInt, ?]])) } { @@ -61,11 +61,11 @@ class RepresentableSuite extends CatsSuite { { //the monadInstance below made a conflict to resolve this one. - implicit val isoFun1: Isomorphisms[String => ?] = Isomorphisms.invariant[String => ?] - - implicit val monadInstance = Representable.monad[String => ?] - checkAll("String => ?", MonadTests[String => ?].monad[String, String, String]) + // TODO ceedubs is this needed? + implicit val isoFun1: Isomorphisms[MiniInt => ?] = Isomorphisms.invariant[MiniInt => ?] + implicit val monadInstance = Representable.monad[MiniInt => ?] + checkAll("MiniInt => ?", MonadTests[MiniInt => ?].monad[String, String, String]) } // Syntax tests. If it compiles is "passes" diff --git a/tests/src/test/scala/cats/tests/ShowSuite.scala b/tests/src/test/scala/cats/tests/ShowSuite.scala index 0f70850121..347d519db4 100644 --- a/tests/src/test/scala/cats/tests/ShowSuite.scala +++ b/tests/src/test/scala/cats/tests/ShowSuite.scala @@ -5,14 +5,14 @@ import java.util.concurrent.TimeUnit import cats.Show.ContravariantShow import cats.laws.discipline.arbitrary._ -import cats.laws.discipline.{ContravariantTests, SerializableTests} +import cats.laws.discipline.{ContravariantTests, MiniInt, SerializableTests} import cats.laws.discipline.eq._ import org.scalatest.FunSuite import scala.concurrent.duration.{Duration, FiniteDuration} class ShowSuite extends CatsSuite { - checkAll("Contravariant[Show]", ContravariantTests[Show].contravariant[Int, Int, Int]) + checkAll("Contravariant[Show]", ContravariantTests[Show].contravariant[MiniInt, Int, Boolean]) checkAll("Contravariant[Show]", SerializableTests.serializable(Contravariant[Show])) sealed trait TimeOfDay diff --git a/tests/src/test/scala/cats/tests/Tuple2KSuite.scala b/tests/src/test/scala/cats/tests/Tuple2KSuite.scala index bf9e7be506..64b9f02a54 100644 --- a/tests/src/test/scala/cats/tests/Tuple2KSuite.scala +++ b/tests/src/test/scala/cats/tests/Tuple2KSuite.scala @@ -19,8 +19,8 @@ class Tuple2KSuite extends CatsSuite { checkAll("Alternative[Tuple2K[Option, List, Int]]", SerializableTests.serializable(Alternative[λ[α => Tuple2K[Option, List, α]]])) - checkAll("Tuple2K[Show, Order, Int]", - ContravariantTests[λ[α => Tuple2K[Show, Order, α]]].contravariant[Int, Int, Int]) + checkAll("Tuple2K[Show, Order, MiniInt]", + ContravariantTests[λ[α => Tuple2K[Show, Order, α]]].contravariant[MiniInt, Int, Boolean]) checkAll("Contravariant[Tuple2K[Show, Order, Int]]", SerializableTests.serializable(Contravariant[λ[α => Tuple2K[Show, Order, α]]])) diff --git a/tests/src/test/scala/cats/tests/WriterTSuite.scala b/tests/src/test/scala/cats/tests/WriterTSuite.scala index 2862c193a4..e739b82f41 100644 --- a/tests/src/test/scala/cats/tests/WriterTSuite.scala +++ b/tests/src/test/scala/cats/tests/WriterTSuite.scala @@ -21,7 +21,8 @@ class WriterTSuite extends CatsSuite { checkAll("WriterT[List, Int, Int]", EqTests[WriterT[List, Int, Int]].eqv) checkAll("Eq[WriterT[List, Int, Int]]", SerializableTests.serializable(Eq[WriterT[List, Int, Int]])) - checkAll("WriterT[Show, Int, Int]", ContravariantTests[WriterT[Show, Int, ?]].contravariant[Int, Int, Int]) + checkAll("WriterT[Show, MiniInt, ?]", + ContravariantTests[WriterT[Show, MiniInt, ?]].contravariant[MiniInt, Int, Boolean]) checkAll("Contravariant[WriterT[Show, Int, Int]]", SerializableTests.serializable(Contravariant[WriterT[Show, Int, ?]]))