Search code examples
scalaimplicit

Scala Implicit Ordering


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)
   }
}

Solution

  • 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)
    }