Created
July 2, 2012 01:18
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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