trait Eq[-A] {
def eq(a: A, b: A): Boolean
}
object Eq {
implicit object IntEq extends Eq[Int] {
def eq(a: Int, b: Int) = a == b
}
}
trait Supertrait[+A]
object Supertrait {
implicit def Eq[A: Eq]: Eq[Supertrait[A]] = ???
}
trait Subtrait[+A] extends Supertrait[A]
object Subtrait {
implicit def Eq[A: Eq]: Eq[Subtrait[A]] = ???
}
def f[A](x: Subtrait[A])(implicit ev: Eq[Subtrait[A]]) = ???
f(new Subtrait[Int] {})
编译此代码时,会发生以下错误:
Error:(32, 4) ambiguous implicit values:
both method Eq in object Supertrait of type [A](implicit evidence$1: Eq[A])Eq[Supertrait[A]]
and method Eq in object Subtrait of type [A](implicit evidence$2: Eq[A])Eq[Subtrait[A]]
match expected type Eq[Subtrait[Int]]
f(new Subtrait[Int] {})
^
为什么Subtrait
同伴对象中的implicit def
没有比Supertrait
中的更高的优先级?
我希望子特征的伴随对象中的implicit def
比超特征中的优先级更高。
更新
LowPriorityImplicits
技巧也不起作用。请参阅 在 Scala 中的隐式实例中强制实施优先级。
看起来您的代码违反了隐式的非歧义规则。
摘自 Programming in Scala,第 1 版:
非歧义规则:只有在以下情况下才插入隐式转换 没有其他可能的转换要插入。如果编译器有两个 修复 x + y 的选项,例如使用 convert1(x( + y 或 convert2(x( + y,那么它将报告错误并拒绝在它们之间进行选择。可以定义某种"最佳匹配"规则 更喜欢某些转换而不是其他转换。然而,这样的选择会导致 非常晦涩的代码。假设编译器选择了 convert2,但您 是该文件的新成员,并且只知道 convert1 - 您可以花费 很多时候认为已经应用了不同的转换!
完整的文本可以在这里找到。