Skip to content

Commit

Permalink
Add {C,c}omparison to Order, fixes #1101
Browse files Browse the repository at this point in the history
  • Loading branch information
adelbertc committed Jun 9, 2016
1 parent 88cbe95 commit b8bf39d
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 1 deletion.
23 changes: 22 additions & 1 deletion kernel-laws/src/test/scala/cats/kernel/laws/LawTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import cats.kernel.std.all._

import org.typelevel.discipline.{ Laws }
import org.typelevel.discipline.scalatest.Discipline
import org.scalacheck.{ Arbitrary }
import org.scalacheck.{ Arbitrary, Gen }
import Arbitrary.arbitrary
import org.scalatest.FunSuite
import scala.util.Random
Expand Down Expand Up @@ -79,6 +79,27 @@ class LawTests extends FunSuite with Discipline {
laws[GroupLaws, (Int, Int)].check(_.band)

laws[GroupLaws, Unit].check(_.boundedSemilattice)

// Comparison related
implicit val arbitraryComparison: Arbitrary[Comparison] =
Arbitrary(Gen.oneOf(Comparison.GreaterThan, Comparison.EqualTo, Comparison.LessThan))

laws[OrderLaws, Comparison].check(_.eqv)

test("comparison") {
val order = Order[Int]
val eqv = Eq[Comparison]
eqv.eqv(order.comparison(1, 0), Comparison.GreaterThan) &&
eqv.eqv(order.comparison(0, 0), Comparison.EqualTo) &&
eqv.eqv(order.comparison(-1, 0), Comparison.LessThan)
}

test("signum . toInt . comparison = signum . compare") {
check { (i: Int, j: Int) =>
Eq[Int].eqv(Order[Int].comparison(i, j).toInt.signum, Order[Int].compare(i, j).signum)
}
}

// esoteric machinery follows...

implicit lazy val band: Band[(Int, Int)] =
Expand Down
19 changes: 19 additions & 0 deletions kernel/src/main/scala/cats/kernel/Comparison.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package cats.kernel

/** ADT encoding the possible results of a comparison */
sealed abstract class Comparison extends Product with Serializable {
/** The signum of this comparison */
def toInt: Int = this match {
case Comparison.GreaterThan => 1
case Comparison.EqualTo => 0
case Comparison.LessThan => -1
}
}

object Comparison {
final case object GreaterThan extends Comparison
final case object EqualTo extends Comparison
final case object LessThan extends Comparison

implicit val catsKernelEqForComparison: Eq[Comparison] = Eq.fromUniversalEquals
}
11 changes: 11 additions & 0 deletions kernel/src/main/scala/cats/kernel/Order.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ trait Order[@sp A] extends Any with PartialOrder[A] { self =>
*/
def compare(x: A, y: A): Int

/**
* Like `compare`, but returns a [[cats.kernel.Comparison]] instead of an Int.
* Has the benefit of being able to pattern match on, but not as performant.
*/
def comparison(x: A, y: A): Comparison = {
val r = compare(x, y)
if (r > 0) Comparison.GreaterThan
else if (r == 0) Comparison.EqualTo
else Comparison.LessThan
}

def partialCompare(x: A, y: A): Double = compare(x, y).toDouble

/**
Expand Down

0 comments on commit b8bf39d

Please sign in to comment.