Knut Arne Vedaa Knut Arne Vedaa - 1 month ago 11
Scala Question

Ordering and Ordered and comparing Options


case class Person(name: String)

and trying to do:

scala> List(Person("Tom"), Person("Bob")).sorted

results in a complaint about missing Ordering.

<console>:8: error: could not find implicit value for parameter ord: Ordering[Person]
List(Person("Tom"), Person("Bob")).sorted

However this:

case class Person(name: String) extends Ordered[Person] {
def compare(that: Person) = compare }

works fine as expected:

scala> List(Person("Tom"), Person("Bob")).sorted
res12: List[Person] = List(Person(Bob), Person(Tom))

although there's no Ordering or implicits involved.

Question #1: what's going on here? (My money is on something implicit...)

However, given the above and the fact that this:

scala> Person("Tom") > Person("Bob")
res15: Boolean = true

works, and that also this:

scala> List(Some(2), None, Some(1)).sorted

works out of the box:

res13: List[Option[Int]] = List(None, Some(1), Some(2))

I would expect that this:

scala> Some(2) > Some(1)

would also work, however it does not:

<console>:6: error: value > is not a member of Some[Int]
Some(2) > Some(1)

Question #2: why not, and how can I get it to work?


Concerning your first question: Ordered[T] extends Comparable[T]. The Ordering companion object provides an implicit Ordering[T] for any value that can be converted into a Comparable[T]:

implicit def ordered[A <% Comparable[A]]: Ordering[A]

There is no implicit conversion A : Ordering => Ordered[A] - that's why Some(1) > Some(2) will not work.

It is questionable if it is a good idea to define such a conversion as you may end up wrapping your objects into Ordered instances and then create an Ordering of that again (and so on...). Even worse: you could create two Ordered instances with different Ordering instances in scope which is of course not what you want.