伴随对象中的 Scala 隐式类型类优先级


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 - 您可以花费 很多时候认为已经应用了不同的转换!

完整的文本可以在这里找到。

最新更新