zcbzfl zcbzfl - 2 months ago 30
Scala Question

Scala view bounds, what's wrong with my example

I use the below example to strengthen understanding of Scala view bounds:

case class Person(age: Int)
object P003 {
implicit def m(p: Person) = new Ordering[Person] {
override def compare(x: Person, y: Person): Int = {
x.age - y.age
}
}

def sort[T <% Ordering[T]](list: List[T]) = list.sorted

def main(args: Array[String]): Unit = {
val list = List(Person(10), Person(2), Person(8))
println(sort(list))
}


but errors thrown out when compiled:

Failure

I can't find out why, appreciate if someone offer any help.

Answer

Scala View Bounds was a mechanism to allow you to view a type A as type B. In your example, it looks like you've mixed Ordering[T] with Ordered[T]. When a class implements Ordered[T] with an addition of view bounds, it allows you to view the T as Ordered[T]. With your example, it allows you to look at a Person as an Ordered[Person], and provide that as an implicit order for list.sort.

This is what your class actually should of looked like:

case class Person(age: Int) extends Ordered[Person] {
  override def compare(that: Person): Int = this.age - that.age
}

And then:

object P003 {
  def sort[T <% Ordered[T]](list: List[T]) = list.sorted

  def main(args: Array[String]): Unit = {
    val list = List(Person(10), Person(2), Person(8))
    println(sort(list))
  }
}

Yields:

List(Person(2), Person(8), Person(10))

But, View Bounds was deprecated (there is a rather long discussion here in regards to that). You can achieve the same with a Context Bound and Ordering.by:

case class Person(age: Int)

object P003 {
  implicit def personOrdering: Ordering[Person] = Ordering.by(p => p.age)

  def sort[T: Ordering](list: List[T]) = list.sorted

  def main(args: Array[String]): Unit = {
    val list = List(Person(10), Person(2), Person(8))
    println(sort(list))
  }
}