Skip to content

Commit

Permalink
Add PartialOrder and Eq instances for XorT
Browse files Browse the repository at this point in the history
Fixes #664.
  • Loading branch information
ceedubs committed Nov 17, 2015
1 parent 1ca7970 commit 7249b4d
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 4 deletions.
36 changes: 32 additions & 4 deletions core/src/main/scala/cats/data/XorT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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]] =
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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
}
15 changes: 15 additions & 0 deletions tests/src/test/scala/cats/tests/XorTTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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
Expand All @@ -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, ?]]
Expand Down

0 comments on commit 7249b4d

Please sign in to comment.