From 71bbf398514a67a5d4b3250d998a2b909452b9c3 Mon Sep 17 00:00:00 2001 From: Jacob Wang Date: Tue, 11 Jun 2019 17:50:35 +0100 Subject: [PATCH] Add Order instance for NonEmptySet (#2779) (#2787) * Add Order instance for NonEmptySet (#2779) - Add Serializable tests for NonEmptySet instances * remove old catsDataEqForNonEmptySet. Name Order instance properly * Add CatsDataMimaException to test cats.data package private binary compatibility. Simplify NonEmptySet instances hierachy * Fix compile error * remove redundant tests --- .../main/scala/cats/data/NonEmptySet.scala | 28 ++++++++++++++++--- .../scala/cats/tests/NonEmptySetSuite.scala | 21 +++++++++++++- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/core/src/main/scala/cats/data/NonEmptySet.scala b/core/src/main/scala/cats/data/NonEmptySet.scala index 14b25de7f4..894cc1f011 100644 --- a/core/src/main/scala/cats/data/NonEmptySet.scala +++ b/core/src/main/scala/cats/data/NonEmptySet.scala @@ -19,6 +19,7 @@ package data import cats.instances.sortedSet._ import cats.kernel._ +import cats.syntax.order._ import scala.collection.immutable._ @@ -358,7 +359,7 @@ sealed class NonEmptySetOps[A](val value: NonEmptySet[A]) { } } -sealed abstract private[data] class NonEmptySetInstances { +sealed abstract private[data] class NonEmptySetInstances extends NonEmptySetInstances0 { implicit val catsDataInstancesForNonEmptySet: SemigroupK[NonEmptySet] with Reducible[NonEmptySet] = new SemigroupK[NonEmptySet] with Reducible[NonEmptySet] { @@ -405,9 +406,9 @@ sealed abstract private[data] class NonEmptySetInstances { fa.toNonEmptyList } - implicit def catsDataEqForNonEmptySet[A: Order]: Eq[NonEmptySet[A]] = - new Eq[NonEmptySet[A]] { - def eqv(x: NonEmptySet[A], y: NonEmptySet[A]): Boolean = x === y + implicit def catsDataOrderForNonEmptySet[A](implicit A: Order[A]): Order[NonEmptySet[A]] = + new NonEmptySetOrder[A] { + implicit override def A0: Order[A] = A } implicit def catsDataShowForNonEmptySet[A](implicit A: Show[A]): Show[NonEmptySet[A]] = @@ -417,3 +418,22 @@ sealed abstract private[data] class NonEmptySetInstances { def combine(x: NonEmptySet[A], y: NonEmptySet[A]): NonEmptySet[A] = x | y } } + +sealed abstract private[data] class NonEmptySetInstances0 { + implicit def catsDataEqForNonEmptySet[A](implicit A: Order[A]): Eq[NonEmptySet[A]] = new NonEmptySetEq[A] { + implicit override def A0: Eq[A] = A + } +} + +sealed abstract private[data] class NonEmptySetOrder[A] extends Order[NonEmptySet[A]] with NonEmptySetEq[A] { + implicit override def A0: Order[A] + + override def compare(x: NonEmptySet[A], y: NonEmptySet[A]): Int = + x.toSortedSet.compare(y.toSortedSet) +} + +sealed private[data] trait NonEmptySetEq[A] extends Eq[NonEmptySet[A]] { + implicit def A0: Eq[A] + + override def eqv(x: NonEmptySet[A], y: NonEmptySet[A]): Boolean = x === y +} diff --git a/tests/src/test/scala/cats/tests/NonEmptySetSuite.scala b/tests/src/test/scala/cats/tests/NonEmptySetSuite.scala index f65b86061a..8846062861 100644 --- a/tests/src/test/scala/cats/tests/NonEmptySetSuite.scala +++ b/tests/src/test/scala/cats/tests/NonEmptySetSuite.scala @@ -20,17 +20,36 @@ package tests import cats.laws.discipline._ import cats.laws.discipline.arbitrary._ import cats.data.NonEmptySet -import cats.kernel.laws.discipline.{EqTests, SemilatticeTests} +import cats.kernel.Semilattice +import cats.kernel.laws.discipline.{EqTests, OrderTests, PartialOrderTests, SemilatticeTests} import scala.collection.immutable.SortedSet class NonEmptySetSuite extends CatsSuite { checkAll("NonEmptySet[Int]", SemigroupKTests[NonEmptySet].semigroupK[Int]) + checkAll("SemigroupK[NonEmptySet[A]]", SerializableTests.serializable(SemigroupK[NonEmptySet])) + checkAll("NonEmptySet[Int]", ReducibleTests[NonEmptySet].reducible[Option, Int, Int]) + checkAll("Reducible[NonEmptySet]", SerializableTests.serializable(Reducible[NonEmptySet])) + checkAll("NonEmptySet[String]", SemilatticeTests[NonEmptySet[String]].band) + checkAll("Semilattice[NonEmptySet]", SerializableTests.serializable(Semilattice[NonEmptySet[String]])) + checkAll("NonEmptySet[String]", EqTests[NonEmptySet[String]].eqv) + { + implicit val A = ListWrapper.order[Int] + checkAll("Eq[NonEmptySet[ListWrapper[Int]]]", SerializableTests.serializable(Eq[NonEmptySet[ListWrapper[Int]]])) + + checkAll("NonEmptySet[ListWrapper[Int]]", OrderTests[NonEmptySet[ListWrapper[Int]]].order) + checkAll("Order[NonEmptySet[ListWrapper[Int]]]", + SerializableTests.serializable(Order[NonEmptySet[ListWrapper[Int]]])) + + Eq[NonEmptySet[ListWrapper[Int]]] + PartialOrder[NonEmptySet[ListWrapper[Int]]] + } + test("First element is always the smallest") { forAll { (nes: NonEmptySet[Int]) => nes.forall { v =>