Skip to content

Instantly share code, notes, and snippets.

@robinp
Created September 12, 2012 10:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robinp/3705819 to your computer and use it in GitHub Desktop.
Save robinp/3705819 to your computer and use it in GitHub Desktop.
automatic Ordering for case classes using shapeless
package shapeless
import shapeless._
import HList._
package object autoordering extends App {
type Iso[T, L <: HList] = HListIso[T, L]
implicit def ccOrdering[C, L <: HList](implicit iso: Iso[C, L], L: Ordering[L]) = new Ordering[C] {
def compare(x: C, y: C) = L.compare(iso.toHList(x), iso.toHList(y))
}
implicit def hnilOrdering: Ordering[HNil] = new Ordering[HNil] {
def compare(x: HNil, y: HNil) = 0
}
implicit def hlistOrdering[H, T <: HList](implicit H : Ordering[H], T : Ordering[T]) : Ordering[H :: T] = new Ordering[H :: T] {
def compare(x: H :: T, y: H :: T) = {
val hcmp = H.compare(x.head, y.head)
if (hcmp == 0) T.compare(x.tail, y.tail)
else hcmp
}
}
// A pair of arbitrary case classes
case class Foo(i : Int, s : String)
case class Bar(b : Boolean, s : String, d : Double)
// Publish their `HListIso`'s
implicit def fooIso = HListIso(Foo.apply _, Foo.unapply _)
implicit def barIso = HListIso(Bar.apply _, Bar.unapply _)
// And they have orderings
val fooOrd = implicitly[Ordering[Foo]]
assert(fooOrd.compare(Foo(1, "A"), Foo(0, "A")) > 0)
assert(fooOrd.compare(Foo(0, "A"), Foo(0, "A")) == 0)
assert(fooOrd.compare(Foo(0, "A"), Foo(0, "B")) < 0)
assert(fooOrd.compare(Foo(0, "C"), Foo(0, "B")) > 0)
println("Done")
//
//
//
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment