Knut Arne Vedaa Knut Arne Vedaa - 4 days ago 6
Scala Question

Ordering and Ordered and comparing Options

Given:

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) = this.name compare that.name }


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?

Answer

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.

Comments