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

时间:2018-08-12 07:49:48

标签: scala implicit operator-precedence implicit-parameters

我有这两个隐式

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将被选择。

我知道这是合乎逻辑的,但是为什么会这样呢?我找不到任何地方的文件。

3 个答案:

答案 0 :(得分:4)

Scala Language Specification说:

  

如果有几个与隐式匹配的合格参数   参数的类型,将使用规则选择最具体的类型   静态overloading resolution

重载分辨率的概念是,一个符号比另一个符号更具体。精确的通用通用定义非常复杂(如您在上面的链接说明中所见),但是在您的情况下,可以归结为以下事实:childOfB严格覆盖了product和因此是更具体

答案 1 :(得分:2)

规范says

  

如果有几个与隐式匹配的合格参数   参数的类型,将使用规则选择最具体的类型   静态overloading resolution

答案 2 :(得分:2)

要扩展@ghik的答案,请参见在Scala中编程

  

更准确地说,如果满足以下条件之一,则隐式转换比另一隐式转换更具体:

     
      
  • 前者的论点是后者的论点
  •   
  • 这两个转换都是方法,前者的封闭类扩展了后者的封闭类
  •   

我的猜测是,该引号中的“参数”也指类型参数,如所建议的那样

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