From 7249b4d63a72eb7fc1391e1a8106fb602f94c56a Mon Sep 17 00:00:00 2001 From: Cody Allen Date: Tue, 17 Nov 2015 08:09:24 -0500 Subject: [PATCH] Add PartialOrder and Eq instances for XorT Fixes #664. --- core/src/main/scala/cats/data/XorT.scala | 36 ++++++++++++++++--- .../src/test/scala/cats/tests/XorTTests.scala | 15 ++++++++ 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/core/src/main/scala/cats/data/XorT.scala b/core/src/main/scala/cats/data/XorT.scala index d5a3828568..5bc5669bbe 100644 --- a/core/src/main/scala/cats/data/XorT.scala +++ b/core/src/main/scala/cats/data/XorT.scala @@ -156,10 +156,9 @@ private[data] abstract class XorTInstances extends XorTInstances1 { } */ - implicit def xorTEq[F[_], L, R](implicit e: Eq[F[L Xor R]]): Eq[XorT[F, L, R]] = - // TODO Use Eq.instance on next algebra upgrade - new Eq[XorT[F, L, R]] { - def eqv(x: XorT[F, L, R], y: XorT[F, L, R]): Boolean = e.eqv(x.value, y.value) + implicit def xorTOrder[F[_], L, R](implicit F: Order[F[L Xor R]]): Order[XorT[F, L, R]] = + new XorTOrder[F, L, R] { + val F0: Order[F[L Xor R]] = F } implicit def xorTShow[F[_], L, R](implicit sh: Show[F[L Xor R]]): Show[XorT[F, L, R]] = @@ -200,6 +199,11 @@ private[data] abstract class XorTInstances1 extends XorTInstances2 { new XorTFoldable[F, L] { val F0: Foldable[F] = F } + + implicit def xorTPartialOrder[F[_], L, R](implicit F: PartialOrder[F[L Xor R]]): PartialOrder[XorT[F, L, R]] = + new XorTPartialOrder[F, L, R] { + val F0: PartialOrder[F[L Xor R]] = F + } } private[data] abstract class XorTInstances2 extends XorTInstances3 { @@ -213,6 +217,11 @@ private[data] abstract class XorTInstances2 extends XorTInstances3 { implicit val L0 = L new XorTSemigroupK[F, L] { implicit val F = F0; implicit val L = L0 } } + + implicit def xorTEq[F[_], L, R](implicit F: Eq[F[L Xor R]]): Eq[XorT[F, L, R]] = + new XorTEq[F, L, R] { + val F0: Eq[F[L Xor R]] = F + } } private[data] abstract class XorTInstances3 { @@ -289,3 +298,22 @@ private[data] sealed trait XorTTraverse[F[_], L] extends Traverse[XorT[F, L, ?]] override def traverse[G[_]: Applicative, A, B](fa: XorT[F, L, A])(f: A => G[B]): G[XorT[F, L, B]] = fa traverse f } + +private[data] sealed trait XorTEq[F[_], L, A] extends Eq[XorT[F, L, A]] { + implicit def F0: Eq[F[L Xor A]] + + override def eqv(x: XorT[F, L, A], y: XorT[F, L, A]): Boolean = x === y +} + +private[data] sealed trait XorTPartialOrder[F[_], L, A] extends PartialOrder[XorT[F, L, A]] with XorTEq[F, L, A]{ + override implicit def F0: PartialOrder[F[L Xor A]] + + override def partialCompare(x: XorT[F, L, A], y: XorT[F, L, A]): Double = + x partialCompare y +} + +private[data] sealed trait XorTOrder[F[_], L, A] extends Order[XorT[F, L, A]] with XorTPartialOrder[F, L, A]{ + override implicit def F0: Order[F[L Xor A]] + + override def compare(x: XorT[F, L, A], y: XorT[F, L, A]): Int = x compare y +} diff --git a/tests/src/test/scala/cats/tests/XorTTests.scala b/tests/src/test/scala/cats/tests/XorTTests.scala index 485c750d20..af4ba819b9 100644 --- a/tests/src/test/scala/cats/tests/XorTTests.scala +++ b/tests/src/test/scala/cats/tests/XorTTests.scala @@ -5,6 +5,7 @@ import cats.functor.Bifunctor import cats.data.{Xor, XorT} import cats.laws.discipline.{BifunctorTests, FoldableTests, FunctorTests, MonadErrorTests, MonoidKTests, SerializableTests, TraverseTests} import cats.laws.discipline.arbitrary._ +import algebra.laws.OrderLaws class XorTTests extends CatsSuite { implicit val eq0 = XorT.xorTEq[List, String, String Xor Int] @@ -17,6 +18,8 @@ class XorTTests extends CatsSuite { checkAll("Bifunctor[XorT[List, ?, ?]]", SerializableTests.serializable(Bifunctor[XorT[List, ?, ?]])) checkAll("XorT[List, Int, ?]", TraverseTests[XorT[List, Int, ?]].foldable[Int, Int]) checkAll("Traverse[XorT[List, Int, ?]]", SerializableTests.serializable(Traverse[XorT[List, Int, ?]])) + checkAll("XorT[List, String, Int]", OrderLaws[XorT[List, String, Int]].order) + checkAll("Order[XorT[List, String, Int]]", SerializableTests.serializable(Order[XorT[List, String, Int]])) { implicit val F = ListWrapper.foldable @@ -30,6 +33,18 @@ class XorTTests extends CatsSuite { checkAll("Functor[XorT[ListWrapper, Int, ?]]", SerializableTests.serializable(Functor[XorT[ListWrapper, Int, ?]])) } + { + implicit val F = ListWrapper.partialOrder[String Xor Int] + checkAll("XorT[ListWrapper, String, Int]", OrderLaws[XorT[ListWrapper, String, Int]].partialOrder) + checkAll("PartialOrder[XorT[ListWrapper, String, Int]]", SerializableTests.serializable(PartialOrder[XorT[ListWrapper, String, Int]])) + } + + { + implicit val F = ListWrapper.eqv[String Xor Int] + checkAll("XorT[ListWrapper, String, Int]", OrderLaws[XorT[ListWrapper, String, Int]].eqv) + checkAll("Eq[XorT[ListWrapper, String, Int]]", SerializableTests.serializable(Eq[XorT[ListWrapper, String, Int]])) + } + // make sure that the Monad and Traverse instances don't result in ambiguous // Functor instances Functor[XorT[List, Int, ?]]