隐式解析中的 Scala 类型约束优先级

Scala type constraint precedence in implicit resolution

我有这两个隐式

trait A[T] {
  val name: String
}

trait B

object A {
  implicit def product[T <: Product] = new A[T] {
    override val name: String = "product"
  }

  implicit def childOfB[T <: Product with B] = new A[T] {
    override val name: String = "child of B"
  }
}

如果我尝试找到 A[C] 的隐式实例,其中 C

case class C() extends B

childOfB 将被选中。

我知道这是合乎逻辑的,但为什么会这样?我在任何地方都找不到它的记录。

规格says

If there are several eligible arguments which match the implicit parameter's type, a most specific one will be chosen using the rules of static overloading resolution.

Scala Language Specification 说:

If there are several eligible arguments which match the implicit parameter's type, a most specific one will be chosen using the rules of static overloading resolution.

重载解析的概念是一个符号比其他符号更具体。精确性的一般定义非常复杂(正如您在上面链接的规范中看到的那样),但在您的情况下,它归结为 childOfB 严格涵盖 product 和因此更具体

要扩展@ghik 的回答,来自 Programming in Scala

To be more precise, one implicit conversion is more specific than another if one of the following applies:

  • The argument of the former is a subtype of the latter's
  • Both conversions are methods, and the enclosing class of the former extends the enclosing class of the latter

我的猜测是 "argument" 在该引用中也指类型参数,正如

所建议的那样
object A {
  implicit def A2Z[T <: A] = new Z[T] {println("A")}
  implicit def B2Z[T <: B] = new Z[T] {println("B")}
}

trait A
trait B extends A

trait Z[T]

def aMethod[T <: A](implicit o: Z[T]) = ()

implicit val a: A = new A {}

aMethod // prints B even though we started with an A