From 9bdc67bd017d54e1873fc517879969bba9180047 Mon Sep 17 00:00:00 2001 From: sullis Date: Sun, 17 Dec 2017 07:03:46 -0500 Subject: [PATCH 1/5] sbt-coursier 1.0.0 (#2114) * sbt-coursier 1.0.0 * sbt-coursier 1.0.0 --- project/plugins.sbt | 2 +- project/project/plugins.sbt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 1e25b20265..f4463459c6 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,4 +1,4 @@ -addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC12") +addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0") addSbtPlugin("com.eed3si9n" % "sbt-unidoc" % "0.4.1") addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.6") addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0") diff --git a/project/project/plugins.sbt b/project/project/plugins.sbt index 4bca2834be..aecbe5bd26 100644 --- a/project/project/plugins.sbt +++ b/project/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC11") +addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0") From dda5df3c28a3c31930720eedccd87d259a095b08 Mon Sep 17 00:00:00 2001 From: Cody Allen Date: Sun, 17 Dec 2017 09:48:15 -0800 Subject: [PATCH 2/5] Add comparison method in Order companion object (#2100) * Add comparison method in Order companion object The main goal of this PR was to add syntax for the `Order` and `PartialOrder` syntax (provided via machinist ops) to address [this comment](https://github.com/typelevel/cats/pull/1867#discussion_r138765045). In the process I noticed that the Order companion object didn't have a `comparison` function to forward through to the type class instance like it did for other methods, so I added that. I did notice that the `Order`/`PartialOrder` syntax does work whether or not you take the `Order`/`PartialOrder` instances as implicit parameters to the ops classes. I think that only @non understands quite what's going on with the machinist syntax macros, so I didn't make the changes to take away those implicit parameters without knowing the implications. The tests pass either way, so I think that end-code should work for users either way. * Change PartialOrder syntax tests to handle NaN --- kernel/src/main/scala/cats/kernel/Order.scala | 3 ++ .../test/scala/cats/tests/OrderSuite.scala | 21 +++++++++++++- .../scala/cats/tests/PartialOrderSuite.scala | 28 +++++++++++++++++-- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/kernel/src/main/scala/cats/kernel/Order.scala b/kernel/src/main/scala/cats/kernel/Order.scala index daeb603336..2b580cd142 100644 --- a/kernel/src/main/scala/cats/kernel/Order.scala +++ b/kernel/src/main/scala/cats/kernel/Order.scala @@ -103,6 +103,9 @@ abstract class OrderFunctions[O[T] <: Order[T]] extends PartialOrderFunctions[O] def max[@sp A](x: A, y: A)(implicit ev: O[A]): A = ev.max(x, y) + + def comparison[@sp A](x: A, y: A)(implicit ev: O[A]): Comparison = + ev.comparison(x, y) } trait OrderToOrderingConversion { diff --git a/tests/src/test/scala/cats/tests/OrderSuite.scala b/tests/src/test/scala/cats/tests/OrderSuite.scala index adb5857d78..d93130924b 100644 --- a/tests/src/test/scala/cats/tests/OrderSuite.scala +++ b/tests/src/test/scala/cats/tests/OrderSuite.scala @@ -1,7 +1,7 @@ package cats package tests - +import Helpers.Ord import cats.kernel.laws.discipline.OrderTests class OrderSuite extends CatsSuite { @@ -15,6 +15,25 @@ class OrderSuite extends CatsSuite { checkAll("Double", OrderTests[Double].order) checkAll("Float", OrderTests[Float].order) checkAll("Long", OrderTests[Long].order) + + test("order ops syntax"){ + forAll { (i: Ord, j: Ord) => + (i compare j) should ===(Order.compare(i, j)) + (i min j) should ===(Order.min(i, j)) + (i max j) should === (Order.max(i, j)) + (i comparison j) should ===(Order.comparison(i, j)) + + // partial order syntax should also work when an Order instance exists + (i > j) should ===(PartialOrder.gt(i, j)) + (i >= j) should ===(PartialOrder.gteqv(i, j)) + (i < j) should ===(PartialOrder.lt(i, j)) + (i <= j) should ===(PartialOrder.lteqv(i, j)) + (i partialCompare j) should ===(PartialOrder.partialCompare(i, j)) + (i tryCompare j) should ===(PartialOrder.tryCompare(i, j)) + (i pmin j) should ===(PartialOrder.pmin(i, j)) + (i pmax j) should ===(PartialOrder.pmax(i, j)) + } + } } object OrderSuite { diff --git a/tests/src/test/scala/cats/tests/PartialOrderSuite.scala b/tests/src/test/scala/cats/tests/PartialOrderSuite.scala index 0990617f0b..120b75f40b 100644 --- a/tests/src/test/scala/cats/tests/PartialOrderSuite.scala +++ b/tests/src/test/scala/cats/tests/PartialOrderSuite.scala @@ -1,9 +1,19 @@ package cats package tests - +import Helpers.POrd +import org.scalatest.Assertion class PartialOrderSuite extends CatsSuite { + + /** + * Check that two partial compare results are "the same". + * This works around the fact that `NaN` is not equal to itself. + */ + def checkPartialCompare(res1: Double, res2: Double): Assertion = { + (res1 == res2 || (res1.isNaN && res2.isNaN)) should ===(true) + } + { Invariant[PartialOrder] Contravariant[PartialOrder] @@ -11,7 +21,7 @@ class PartialOrderSuite extends CatsSuite { test("companion object syntax") { forAll { (i: Int, j: Int) => - PartialOrder.partialCompare(i, j) should ===(catsKernelStdOrderForInt.partialCompare(i, j)) + checkPartialCompare(PartialOrder.partialCompare(i, j), catsKernelStdOrderForInt.partialCompare(i, j)) PartialOrder.tryCompare(i, j) should ===(catsKernelStdOrderForInt.tryCompare(i, j)) PartialOrder.pmin(i, j) should ===(catsKernelStdOrderForInt.pmin(i, j)) PartialOrder.pmax(i, j) should ===(catsKernelStdOrderForInt.pmax(i, j)) @@ -21,6 +31,20 @@ class PartialOrderSuite extends CatsSuite { PartialOrder.gt(i, j) should ===(catsKernelStdOrderForInt.gt(i, j)) } } + + test("partial order ops syntax") { + forAll { (i: POrd, j: POrd) => + (i > j) should ===(PartialOrder.gt(i, j)) + (i >= j) should ===(PartialOrder.gteqv(i, j)) + (i < j) should ===(PartialOrder.lt(i, j)) + (i <= j) should ===(PartialOrder.lteqv(i, j)) + + checkPartialCompare(i partialCompare j, PartialOrder.partialCompare(i, j)) + (i tryCompare j) should ===(PartialOrder.tryCompare(i, j)) + (i pmin j) should ===(PartialOrder.pmin(i, j)) + (i pmax j) should ===(PartialOrder.pmax(i, j)) + } + } } object PartialOrderSuite { From 4d92b99c98d51e81551549ad013bf5b15434b5b1 Mon Sep 17 00:00:00 2001 From: "Kai(luo) Wang" Date: Mon, 18 Dec 2017 09:26:26 -0500 Subject: [PATCH 3/5] fix scalafix rules for productL/R (#2117) --- .../rules/src/main/scala/fix/Cats_v1_0_0.scala | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scalafix/rules/src/main/scala/fix/Cats_v1_0_0.scala b/scalafix/rules/src/main/scala/fix/Cats_v1_0_0.scala index b3bd103ebd..b9081cf50b 100644 --- a/scalafix/rules/src/main/scala/fix/Cats_v1_0_0.scala +++ b/scalafix/rules/src/main/scala/fix/Cats_v1_0_0.scala @@ -247,14 +247,14 @@ case class RenameApplyApConst(index: SemanticdbIndex) override def fix(ctx: RuleCtx): Patch = ctx.replaceSymbols( - "_root_.cats.Apply.forEffect." -> "apL", - "_root_.cats.Apply.followedBy." -> "apR", - "_root_.cats.Apply.Ops.forEffect." -> "apL", - "_root_.cats.Apply.Ops.followedBy." -> "apR", - "_root_.cats.NonEmptyParallel.parForEffect." -> "parApL", - "_root_.cats.NonEmptyParallel.parFollowedBy." -> "parApR", - "_root_.cats.FlatMap.forEffectEval." -> "apLEval", - "_root_.cats.FlatMap.followedByEval." -> "apREval", + "_root_.cats.Apply.forEffect." -> "productL", + "_root_.cats.Apply.followedBy." -> "productR", + "_root_.cats.Apply.Ops.forEffect." -> "productL", + "_root_.cats.Apply.Ops.followedBy." -> "productR", + "_root_.cats.NonEmptyParallel.parForEffect." -> "parProductL", + "_root_.cats.NonEmptyParallel.parFollowedBy." -> "parProductR", + "_root_.cats.FlatMap.forEffectEval." -> "productLEval", + "_root_.cats.FlatMap.followedByEval." -> "productREval", ) } From 95f58ffe14849bcf3e942f34156e5419f06d9c13 Mon Sep 17 00:00:00 2001 From: Kailuo Wang Date: Mon, 18 Dec 2017 11:10:10 -0500 Subject: [PATCH 4/5] use uinit for laws --- laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala | 8 ++++---- .../cats/laws/discipline/InvariantMonoidalTests.scala | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala b/laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala index b3a65d5ce6..528bd7ae72 100644 --- a/laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala +++ b/laws/src/main/scala/cats/laws/InvariantMonoidalLaws.scala @@ -9,11 +9,11 @@ trait InvariantMonoidalLaws[F[_]] extends InvariantSemigroupalLaws[F] { import cats.syntax.semigroupal._ import cats.syntax.invariant._ - def invariantMonoidalLeftIdentity[A, B](fa: F[A], b: B): IsEq[F[A]] = - F.point(b).product(fa).imap(_._2)(a => (b, a)) <-> fa + def invariantMonoidalLeftIdentity[A, B](fa: F[A]): IsEq[F[A]] = + F.unit.product(fa).imap(_._2)(a => ((), a)) <-> fa - def invariantMonoidalRightIdentity[A, B](fa: F[A], b: B): IsEq[F[A]] = - fa.product(F.point(b)).imap(_._1)(a => (a, b)) <-> fa + def invariantMonoidalRightIdentity[A, B](fa: F[A]): IsEq[F[A]] = + fa.product(F.unit).imap(_._1)(a => (a, ())) <-> fa def invariantMonoidalAssociativity[A, B, C](fa: F[A], fb: F[B], fc: F[C]): IsEq[F[(A, (B, C))]] = diff --git a/laws/src/main/scala/cats/laws/discipline/InvariantMonoidalTests.scala b/laws/src/main/scala/cats/laws/discipline/InvariantMonoidalTests.scala index c9240c8d37..0f868c1ebd 100644 --- a/laws/src/main/scala/cats/laws/discipline/InvariantMonoidalTests.scala +++ b/laws/src/main/scala/cats/laws/discipline/InvariantMonoidalTests.scala @@ -27,8 +27,8 @@ trait InvariantMonoidalTests[F[_]] extends InvariantSemigroupalTests[F] { val parents = Seq(invariant[A, B, C], semigroupal[A, B, C]) val bases = Seq.empty val props = Seq( - "invariant monoidal left identity" -> forAll((fa: F[A], b: B) => laws.invariantMonoidalLeftIdentity(fa, b)), - "invariant monoidal right identity" -> forAll((fa: F[A], b: B) => laws.invariantMonoidalRightIdentity(fa, b)), + "invariant monoidal left identity" -> forAll((fa: F[A]) => laws.invariantMonoidalLeftIdentity(fa)), + "invariant monoidal right identity" -> forAll((fa: F[A]) => laws.invariantMonoidalRightIdentity(fa)), "invariant monoidal associativity" -> forAll((fa: F[A], fb: F[B], fc: F[C]) => laws.invariantMonoidalAssociativity(fa, fb, fc)) ) } From 4b73af899c86242da3ea9ca77c8c2b0e0f60426c Mon Sep 17 00:00:00 2001 From: Kailuo Wang Date: Mon, 18 Dec 2017 15:06:19 -0500 Subject: [PATCH 5/5] improve test coverage --- core/src/main/scala/cats/data/Const.scala | 10 --------- .../main/scala/cats/data/IndexedStateT.scala | 4 ---- .../scala/cats/instances/partialOrder.scala | 7 ++++-- .../cats/instances/partialOrdering.scala | 6 +++-- tests/src/test/scala/cats/tests/EqSuite.scala | 22 +++++++------------ .../scala/cats/tests/IndexedStateTSuite.scala | 9 +------- .../test/scala/cats/tests/OrderSuite.scala | 8 ++++++- .../scala/cats/tests/PartialOrderSuite.scala | 7 ++++++ .../cats/tests/PartialOrderingSuite.scala | 3 +++ 9 files changed, 35 insertions(+), 41 deletions(-) diff --git a/core/src/main/scala/cats/data/Const.scala b/core/src/main/scala/cats/data/Const.scala index 97c5b033d9..631a9327cd 100644 --- a/core/src/main/scala/cats/data/Const.scala +++ b/core/src/main/scala/cats/data/Const.scala @@ -135,16 +135,6 @@ private[data] sealed abstract class ConstInstances0 extends ConstInstances1 { } private[data] sealed abstract class ConstInstances1 { - implicit def catsConstInvariantMonoidal[C: Monoid]: InvariantMonoidal[Const[C, ?]] = new InvariantMonoidal[Const[C, ?]] { - def unit: Const[C, Unit] = - Const.empty - - def imap[A, B](fa: Const[C, A])(f: A => B)(g: B => A): Const[C, B] = - fa.retag[B] - - def product[A, B](fa: Const[C, A], fb: Const[C, B]): Const[C, (A, B)] = - fa.retag[(A, B)] combine fb.retag[(A, B)] - } implicit def catsDataEqForConst[A: Eq, B]: Eq[Const[A, B]] = new Eq[Const[A, B]] { def eqv(x: Const[A, B], y: Const[A, B]): Boolean = diff --git a/core/src/main/scala/cats/data/IndexedStateT.scala b/core/src/main/scala/cats/data/IndexedStateT.scala index e0bab8fb6c..d6b6c2e4d3 100644 --- a/core/src/main/scala/cats/data/IndexedStateT.scala +++ b/core/src/main/scala/cats/data/IndexedStateT.scala @@ -247,10 +247,6 @@ private[data] sealed abstract class IndexedStateTInstances extends IndexedStateT implicit def catsDataAlternativeForIndexedStateT[F[_], S](implicit FM: Monad[F], FA: Alternative[F]): Alternative[IndexedStateT[F, S, S, ?]] with Monad[IndexedStateT[F, S, S, ?]] = new IndexedStateTAlternative[F, S] { implicit def F = FM; implicit def G = FA } - - implicit def catsDataContravariantMonoidalForIndexedStateT[F[_], S](implicit FD: ContravariantMonoidal[F], - FA: Applicative[F]): ContravariantMonoidal[IndexedStateT[F, S, S, ?]] = - new IndexedStateTContravariantMonoidal[F, S] { implicit def F = FD; implicit def G = FA } } private[data] sealed abstract class IndexedStateTInstances1 extends IndexedStateTInstances2 { diff --git a/core/src/main/scala/cats/instances/partialOrder.scala b/core/src/main/scala/cats/instances/partialOrder.scala index 671e0b82cf..ec5024e8bc 100644 --- a/core/src/main/scala/cats/instances/partialOrder.scala +++ b/core/src/main/scala/cats/instances/partialOrder.scala @@ -1,9 +1,10 @@ package cats package instances +import cats.kernel.instances.unit._ trait PartialOrderInstances { - implicit val catsContravariantSemigroupalForPartialOrder: ContravariantSemigroupal[PartialOrder] = - new ContravariantSemigroupal[PartialOrder] { + implicit val catsContravariantMonoidalForPartialOrder: ContravariantMonoidal[PartialOrder] = + new ContravariantMonoidal[PartialOrder] { /** Derive a `PartialOrder` for `B` given a `PartialOrder[A]` and a function `B => A`. * * Note: resulting instances are law-abiding only when the functions used are injective (represent a one-to-one mapping) @@ -17,5 +18,7 @@ trait PartialOrderInstances { if (z == 0.0) fb.partialCompare(x._2, y._2) else z } } + + def unit: PartialOrder[Unit] = Order[Unit] } } diff --git a/core/src/main/scala/cats/instances/partialOrdering.scala b/core/src/main/scala/cats/instances/partialOrdering.scala index d44d33e185..3560286635 100644 --- a/core/src/main/scala/cats/instances/partialOrdering.scala +++ b/core/src/main/scala/cats/instances/partialOrdering.scala @@ -2,8 +2,8 @@ package cats package instances trait PartialOrderingInstances { - implicit val catsContravariantSemigroupalForPartialOrdering: ContravariantSemigroupal[PartialOrdering] = - new ContravariantSemigroupal[PartialOrdering] { + implicit val catsContravariantMonoidalForPartialOrdering: ContravariantMonoidal[PartialOrdering] = + new ContravariantMonoidal[PartialOrdering] { /** Derive a `PartialOrdering` for `B` given a `PartialOrdering[A]` and a function `B => A`. * * Note: resulting instances are law-abiding only when the functions used are injective (represent a one-to-one mapping) @@ -24,5 +24,7 @@ trait PartialOrderingInstances { case option => option } } + + def unit: PartialOrdering[Unit] = cats.instances.unit.catsKernelStdOrderForUnit.toOrdering } } diff --git a/tests/src/test/scala/cats/tests/EqSuite.scala b/tests/src/test/scala/cats/tests/EqSuite.scala index 56fea4358c..7b70689a01 100644 --- a/tests/src/test/scala/cats/tests/EqSuite.scala +++ b/tests/src/test/scala/cats/tests/EqSuite.scala @@ -1,26 +1,20 @@ package cats package tests -import org.scalatest._ +import cats.kernel.laws.discipline.SerializableTests +import cats.laws.discipline.ContravariantMonoidalTests +import cats.laws.discipline.arbitrary._ +import cats.laws.discipline.eq._ -class EqSuite extends FunSuite { - { - import cats.implicits._ +class EqSuite extends CatsSuite { Invariant[Eq] Contravariant[Eq] Semigroupal[Eq] ContravariantSemigroupal[Eq] - ContravariantMonoidal[Eq] - } - { - import cats.instances.eq._ - Invariant[Eq] - Contravariant[Eq] - Semigroupal[Eq] - ContravariantSemigroupal[Eq] - ContravariantMonoidal[Eq] - } + checkAll("Eq[Int]", ContravariantMonoidalTests[Eq].contravariantMonoidal[Int, Int, Int]) + checkAll("ContravariantMonoidal[Eq]", SerializableTests.serializable(ContravariantMonoidal[Eq])) + } diff --git a/tests/src/test/scala/cats/tests/IndexedStateTSuite.scala b/tests/src/test/scala/cats/tests/IndexedStateTSuite.scala index 8eef8ecedc..015e75b3fd 100644 --- a/tests/src/test/scala/cats/tests/IndexedStateTSuite.scala +++ b/tests/src/test/scala/cats/tests/IndexedStateTSuite.scala @@ -2,7 +2,7 @@ package cats package tests import cats.arrow.{Profunctor, Strong} -import cats.data.{Const, EitherT, IndexedStateT, State, StateT} +import cats.data.{EitherT, IndexedStateT, State, StateT} import cats.arrow.Profunctor import cats.kernel.instances.tuple._ @@ -372,13 +372,6 @@ class IndexedStateTSuite extends CatsSuite { SemigroupK[IndexedStateT[ListWrapper, Int, Int, ?]] } - { - // F has a ContravariantMonoidal - val SD = ContravariantMonoidal[StateT[Const[String, ?], String, ?]] - - checkAll("ContravariantMonoidal[StateT[Const[String, ?], String, ?]]", SerializableTests.serializable(SD)) - } - { implicit val iso = SemigroupalTests.Isomorphisms.invariant[State[Long, ?]] diff --git a/tests/src/test/scala/cats/tests/OrderSuite.scala b/tests/src/test/scala/cats/tests/OrderSuite.scala index d93130924b..db973db828 100644 --- a/tests/src/test/scala/cats/tests/OrderSuite.scala +++ b/tests/src/test/scala/cats/tests/OrderSuite.scala @@ -2,7 +2,10 @@ package cats package tests import Helpers.Ord -import cats.kernel.laws.discipline.OrderTests +import cats.kernel.laws.discipline.{OrderTests, SerializableTests} +import cats.laws.discipline.ContravariantMonoidalTests +import cats.laws.discipline.arbitrary._ +import cats.laws.discipline.eq._ class OrderSuite extends CatsSuite { { @@ -16,6 +19,9 @@ class OrderSuite extends CatsSuite { checkAll("Float", OrderTests[Float].order) checkAll("Long", OrderTests[Long].order) + checkAll("Order", ContravariantMonoidalTests[Order].contravariantMonoidal[Int, Int, Int]) + checkAll("ContravariantMonoidal[Order]", SerializableTests.serializable(ContravariantMonoidal[Order])) + test("order ops syntax"){ forAll { (i: Ord, j: Ord) => (i compare j) should ===(Order.compare(i, j)) diff --git a/tests/src/test/scala/cats/tests/PartialOrderSuite.scala b/tests/src/test/scala/cats/tests/PartialOrderSuite.scala index 120b75f40b..5db795ecac 100644 --- a/tests/src/test/scala/cats/tests/PartialOrderSuite.scala +++ b/tests/src/test/scala/cats/tests/PartialOrderSuite.scala @@ -2,7 +2,11 @@ package cats package tests import Helpers.POrd +import cats.kernel.laws.discipline.SerializableTests +import cats.laws.discipline.ContravariantMonoidalTests import org.scalatest.Assertion +import cats.laws.discipline.arbitrary._ +import cats.laws.discipline.eq._ class PartialOrderSuite extends CatsSuite { @@ -19,6 +23,9 @@ class PartialOrderSuite extends CatsSuite { Contravariant[PartialOrder] } + checkAll("PartialOrder[Int]", ContravariantMonoidalTests[PartialOrder].contravariantMonoidal[Int, Int, Int]) + checkAll("ContravariantMonoidal[PartialOrder]", SerializableTests.serializable(ContravariantMonoidal[PartialOrder])) + test("companion object syntax") { forAll { (i: Int, j: Int) => checkPartialCompare(PartialOrder.partialCompare(i, j), catsKernelStdOrderForInt.partialCompare(i, j)) diff --git a/tests/src/test/scala/cats/tests/PartialOrderingSuite.scala b/tests/src/test/scala/cats/tests/PartialOrderingSuite.scala index 81d3e37b2a..4e1c99d657 100644 --- a/tests/src/test/scala/cats/tests/PartialOrderingSuite.scala +++ b/tests/src/test/scala/cats/tests/PartialOrderingSuite.scala @@ -16,4 +16,7 @@ class PartialOrderingSuite extends CatsSuite { checkAll("Contravariant[PartialOrdering]", ContravariantTests[PartialOrdering].contravariant[Int, Int, Int]) checkAll("Semigroupal[PartialOrdering]", SemigroupalTests[PartialOrdering].semigroupal[Int, Int, Int]) checkAll("Contravariant[PartialOrdering]", SerializableTests.serializable(Contravariant[PartialOrdering])) + + checkAll("PartialOrdering[Int]", ContravariantMonoidalTests[PartialOrdering].contravariantMonoidal[Int, Int, Int]) + checkAll("ContravariantMonoidal[PartialOrdering]", SerializableTests.serializable(ContravariantMonoidal[PartialOrdering])) }