Skip to content

Instantly share code, notes, and snippets.

@Blaisorblade
Created July 2, 2012 01:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Blaisorblade/3030361 to your computer and use it in GitHub Desktop.
Save Blaisorblade/3030361 to your computer and use it in GitHub Desktop.
Improve PartialOrdering as defined in the Scala standard library (2.9, 2.10)
//Much of the following code derives from scala.math.Ordering,
//and is released under the Scala LICENSE (http://www.scala-lang.org/node/146)
object BetterPartialOrdering {
trait PartialOrderingFromLteq[T] extends PartialOrdering[T] {
override def tryCompare(x: T, y: T): Option[Int] =
(lteq(x, y), lteq(y, x)) match {
case (true, false) => Some(-1)
case (false, true) => Some(1)
case (true, true) => Some(0)
case _ => None
}
}
trait PartialOrderingFromTryCompare[T] extends PartialOrdering[T] {
override def lteq(x: T, y: T): Boolean = {
//Alternative implementations, IMHO less readable.
//tryCompare(x, y).toRight(false).fold(identity, _ <= 0)
//tryCompare(x, y).map(_ <= 0).getOrElse(false)
tryCompare(x, y) match {
case Some(res) => res <= 0
case None => false
}
}
}
trait PartialOrderingExt[T] extends PartialOrdering[T] {
outer =>
def on[U](f: U => T): PartialOrderingExt[U] = new PartialOrderingExt[U] {
override def lteq(x: U, y: U) = outer.lteq(f(x), f(y))
override def tryCompare(x: U, y: U) = outer.tryCompare(f(x), f(y))
}
class Ops(lhs: T) {
def <(rhs: T) = lt(lhs, rhs)
def <=(rhs: T) = lteq(lhs, rhs)
def >(rhs: T) = gt(lhs, rhs)
def >=(rhs: T) = gteq(lhs, rhs)
def equiv(rhs: T) = outer.equiv(lhs, rhs)
/*
//These option would have to return Option[T] for a PartialOrdering.
def max(rhs: T): T = outer.max(lhs, rhs)
def min(rhs: T): T = outer.min(lhs, rhs)
*/
}
implicit def mkOrderingOps(lhs: T): Ops = new Ops(lhs)
}
object PartialOrderingExt {
def apply[T](implicit ord: PartialOrderingExt[T]) = ord
object Implicits {
implicit def infixOrderingOps[T](x: T)(implicit ord: PartialOrderingExt[T]): PartialOrderingExt[T]#Ops = new ord.Ops(x)
}
implicit def Tuple2[T1, T2](implicit ord1: Ordering[T1], ord2: Ordering[T2]): PartialOrderingExt[(T1, T2)] =
new PartialOrderingExt[(T1, T2)] with PartialOrderingFromTryCompare[(T1, T2)] {
//We have a certain result only if comparison on both sides don't contradict each other.
override def tryCompare(x: (T1, T2), y: (T1, T2)): Option[Int] = {
val compare1 = ord1.compare(x._1, y._1)
val compare2 = ord2.compare(x._2, y._2)
(compare1, compare2) match {
case (a, b) if a == b => Some(a)
case (a, 0) => Some(a)
case (0, b) => Some(b)
case _ => None
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment