Is there a way for me to define the same implicit ordering for two different classes?
I tried to do something along the following lines but it doesn't detect the ordering.
abstract class Common
case class A extends Common
case class B extends Common
implicit val KeyOrdering = new Ordering[Common] {
override def compare(x: Common, y: Common): Int = {
x.toString.compareTo(y.toString)
}
}
As noted by @ntn, the inferred type of your list - the least upper bound of its two elements - is Product with Serializable with Common. As scala.Ordering is not contravariant on its type parameter, implicit resolution fails because it does not hold that Ordering[Common] <: Ordering[Product with Serializable with Common].
You can work around this by writing the implicit ordering so that it always has the exact type of the implicit parameter under consideration:
abstract class Common
case class A() extends Common
case class B() extends Common
object Common {
implicit def ordering[A <: Common]: Ordering[A] = new Ordering[A] {
override def compare(x: A, y: A): Int = {
x.toString.compareTo(y.toString)
}
}
}
Or for concision:
object Common {
implicit def ordering[A <: Common]: Ordering[A] = Ordering.by(_.toString)
}
If you remove the case class for A and B (or even only for one of them), then it works.
For List(A(), B()).sorted, it fails to find an Ordering for Product with Serializable with C, as the base class for A and B is Product with C (due to A and B being both case classes).
If you are creating a list with elements of two different base types, I assume you want a list of type List[C], in which you can declare the elements before using them (or get them from some function which returns type C.
val a: C = A()
val b: C = B()
List(a,b).sorted
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With