From 836d33070f176a7e5cfc6a7c4b6e1aecb7b4b8b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20L=C3=B6vgren?= Date: Fri, 7 Sep 2018 13:02:11 +0100 Subject: [PATCH] Add Order#fromLessThan --- .../test/scala/cats/kernel/laws/LawTests.scala | 1 + kernel/src/main/scala/cats/kernel/Order.scala | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/kernel-laws/src/test/scala/cats/kernel/laws/LawTests.scala b/kernel-laws/src/test/scala/cats/kernel/laws/LawTests.scala index f7f45ae3af..f069d0285a 100644 --- a/kernel-laws/src/test/scala/cats/kernel/laws/LawTests.scala +++ b/kernel-laws/src/test/scala/cats/kernel/laws/LawTests.scala @@ -142,6 +142,7 @@ class Tests extends FunSuite with Discipline { checkAll("fromOrdering[Int]", OrderTests(Order.fromOrdering[Int]).order) checkAll("Order.reverse(Order[Int])", OrderTests(Order.reverse(Order[Int])).order) checkAll("Order.reverse(Order.reverse(Order[Int]))", OrderTests(Order.reverse(Order.reverse(Order[Int]))).order) + checkAll("Order.fromLessThan[Int](_ < _)", OrderTests(Order.fromLessThan[Int](_ < _)).order) checkAll("Monoid[String]", MonoidTests[String].monoid) checkAll("Monoid[String]", SerializableTests.serializable(Monoid[String])) diff --git a/kernel/src/main/scala/cats/kernel/Order.scala b/kernel/src/main/scala/cats/kernel/Order.scala index 595e385a7a..4b67ad8645 100644 --- a/kernel/src/main/scala/cats/kernel/Order.scala +++ b/kernel/src/main/scala/cats/kernel/Order.scala @@ -169,6 +169,23 @@ object Order extends OrderFunctions[Order] with OrderToOrderingConversion { def compare(x: A, y: A) = f(x, y) } + /** + * Define an `Order[A]` using the given 'less than' function `f`. + */ + def fromLessThan[@sp A](f: (A, A) => Boolean): Order[A] = + new Order[A] { + override def compare(x: A, y: A): Int = + if (f(x, y)) -1 else if (f(y, x)) 1 else 0 + + // Overridden for performance (avoids multiple comparisons) + override def eqv(x: A, y: A): Boolean = !(f(x, y) || f(y, x)) + override def neqv(x: A, y: A): Boolean = f(x, y) || f(y, x) + override def lteqv(x: A, y: A): Boolean = !f(y, x) + override def lt(x: A, y: A): Boolean = f(x, y) + override def gteqv(x: A, y: A): Boolean = !f(x, y) + override def gt(x: A, y: A): Boolean = f(y, x) + } + /** * An `Order` instance that considers all `A` instances to be equal. */