2
votes

I have a trait

trait Weight  {
    def getWeight: Int
}

Multiple classes inherits it, example:

case class Test(n: Int) extends Weight  {
  override def getWeight: Int = n
}

Now i want to add sorting ability to all Weight subclasses. I added Ordered to Weight:

trait Weight extends Ordered[Weight] {

  def getWeight: Int

  override def compare(that: Weight): Int = this.getWeight.compareTo(that.getWeight)
}

Try sorting:

val seq = Seq(Test(1), Test(4), Test(3), Test(2))

seq.sorted // error

And it's not compiles:

Error:(74, 6) diverging implicit expansion for type scala.math.Ordering[A$A254.this.Test] starting with method $conforms in object Predef seq.sorted;} ^

Whats i am doing wrong?

2
I think problem is about "this" in trait Weight. on Trait you can't use "this" because you can't instance a traitTizianoreica
I think no, because only sorted, which implicitly uses Ordering raises error.zella
that because, I think, is first time on your code where you call "compare" method - But I could be terribly wrongTizianoreica
I just tried call Test(1).compareTo(Test(2)) and it's okzella
Ok sorry I was wrong. But what about use Ordering trait and not Ordered?Tizianoreica

2 Answers

1
votes

Your solution does not work because Ordered[T] is invariant in T, meaning that Ordered[Weight] has no relationship with Ordered[A]. You would need to specify that in the sub-classes.

You could use an implicit Ordering rather than an Ordered.

trait Weight{
  def getWeight : Int
}

object Weight{
  implicit def ordering[T <: Weight] : Ordering[T] = Ordering.by(w => w.getWeight)
}
  case class A(w : Int) extends Weight{
  def getWeight = w
}
case class B(w : Int) extends Weight{
  def getWeight = w
}

import Weight._

Seq(A(1),B(2),B(0),A(3),A(-3)).sorted 

Will result in:

List(A(-3), B(0), A(1), B(2), A(3))

Note that this solution relies on an Ordering[Int] to be available (which is, by default).

2
votes

Another solution a bit different than mdm. Since sorted takes an implicit of Ordering, you can do the following:

seq.sorted(Ordering[Weight])