Reputation: 13
trait LowPriorityOrderingImplicits {
/** This would conflict with all the nice implicit Orderings
* available, but thanks to the magic of prioritized implicits
* via subclassing we can make `Ordered[A] => Ordering[A]` only
* turn up if nothing else works. Since `Ordered[A]` extends
* `Comparable[A]` anyway, we can throw in some Java interop too.
*/
implicit def ordered[A <% Comparable[A]]: Ordering[A] = new Ordering[A] {
def compare(x: A, y: A): Int = x compareTo y
}
implicit def comparatorToOrdering[A](implicit cmp: Comparator[A]): Ordering[A] = new Ordering[A] {
def compare(x: A, y: A) = cmp.compare(x, y)
}
}
there, two implicit function( ordered[A] and comparatorToOrdering[A]) all return Ordering[A], it should conflict, but why dose it work there?
Upvotes: 1
Views: 255
Reputation: 55569
Only if for some type A
there exists an implicit converstion A => Comparable[A]
and an implicit Comparator[A]
. The only way for those implicits to result in something ambiguous is if their own implicit parameters both resolve. In this case it would fail:
class Foo
implicit val fooComp = new java.util.Comparator[Foo] { def compare(a: Foo, b: Foo): Int = 0 }
val fooComparable = new java.lang.Comparable[Foo] { def compareTo(foo: Foo): Int = 0 }
implicit def foo2Comp(foo: Foo): Comparable[Foo] = fooComparable
scala> implicitly[Ordering[Foo]]
<console>:16: error: ambiguous implicit values:
both method ordered in trait LowPriorityOrderingImplicits of type [A](implicit evidence$1: A => Comparable[A])scala.math.Ordering[A]
and method comparatorToOrdering in trait LowPriorityOrderingImplicits of type [A](implicit cmp: java.util.Comparator[A])scala.math.Ordering[A]
match expected type Ordering[Foo]
implicitly[Ordering[Foo]]
^
So it is technically possible to get an ambiguous implicits error, but it should be exceedingly rare. If something is already Comparable
, there is no need for it to have an implicit Comparator
.
Upvotes: 2