Implicit parameter resolution given multiple type

2019-07-24 20:50发布

问题:

I'm using a type class that requires its types A to have instances of Scalaz's Order[A]. In my use case, A is a Java class--in particular Joda Time's LocalDate. This class has a natural ordering as it implements Comparable.

I couldn't find an Order instance for Comparables in Scalaz itself, so I tried writing one myself:

implicit def comparableOrder[A, B]
  (implicit ev0: <:<[A, B],
            ev1: <:<[A, Comparable[B]]): Order[A] = new Order[A] {
  override def order(x: A, y: A): Ordering = Ordering.fromInt(x.compareTo(y))
}

However, even after putting this definition into scope, the following lines fail to compile:

implicitly[Order[LocalDate]]
implicitly[Order[LocalDate <:< Comparable[LocalDate]]]

However, the following does:

implicitly[Order[LocalDate <:< Comparable[ReadablePartial]]]

As does the following after I hard-code an implicit val containing the Order instance I'm looking for:

implicit val localDateOrder = comparableOrder[LocalDate, ReadablePartial]
implicitly[Order[LocalDate]]

Is there a way I can get the Scala compiler to pick up this instance automatically? The implicit val works in this case but quickly becomes unwieldy with nested structures. I'm using Scala 2.10.4.

EDIT: I've also tried to test this on As that implement Comparable[A] rather than Comparable[B] where B is a superclass of A. It still doesn't seem to work:

class MyInt(n: Int) extends Comparable[Int] {
  override def compareTo(o: Int): Int = n - o
}
implicit def comparableOrder[A <: Comparable[A]]: Order[A] = new Order[A] {
  override def order(x: A, y: A): Ordering = Ordering.fromInt(x.compareTo(y))
}
implicitly[Order[MyInt]]