Ordering case classes

Scala provides lexicographic Ordering instances for TupleN types when all of the element types have Ordering instances. It doesn’t provide the same instances for case classes, however—probably just because lexicographic order isn’t what you want for case classes as often as it is for tuples.

Sometimes you actually do want a lexicographic ordering for your case classes, though, and Scala unfortunately doesn’t provide any nice boilerplate-free way to create such orderings. This post will provide a quick sketch of two approaches to filling this gap: one using macros, and one using Shapeless 2.0’s new Generic machinery and the TypeClass type class.

First for a case class to use as a running example, along with some instances:

Let’s quickly confirm that there’s no Ordering[Foo] already sitting around:

Yep, we’re going to have to take care of this ourselves.

First for the macro solution (note that I’m using quasiquotes, which are available in Scala 2.10 as a plugin):

Apart from the fact that we need to confirm that we don’t have a tuple (which would throw us into an infinitely recursive implicit search and crash the compiler), this is pretty straightforward stuff—we just collect all the case accessors and plop them into a tuple, which we know how to order lexicographically.

One import, and we’re done:

This is all fairly nice and type-safe, in the sense that if our case class has an unordered member, we get a reasonably helpful compile-time error:

And even that could be pretty easily improved. It’s still arguably kind of clunky and ad-hoc, though, which is where Shapeless comes in. With Lars Hupel’s ProductTypeClass type class, we can just describe how to build up lexicographic ordering instances:

And Generic will take care of (almost all of) the rest.

Much nicer!