Scala:隐式参数解析优先级

标签 scala implicit

假设我们有只涉及局部范围的隐式参数查找:

trait CanFoo[A] {
  def foos(x: A): String
}

object Def {
  implicit object ImportIntFoo extends CanFoo[Int] {
    def foos(x: Int) = "ImportIntFoo:" + x.toString
  }
}

object Main {
  def test(): String = {
    implicit object LocalIntFoo extends CanFoo[Int] {
      def foos(x: Int) = "LocalIntFoo:" + x.toString
    }
    import Def._

    foo(1)
  }

  def foo[A:CanFoo](x: A): String = implicitly[CanFoo[A]].foos(x)
}

在上面的代码中,LocalIntFoo胜过ImportedIntFoo .
有人可以解释如何使用“静态重载解决规则(§6.26.3)”来更具体地考虑它吗?

编辑 :

名称绑定(bind)优先级是一个令人信服的论点,但有几个问题尚未解决。
首先,Scala 语言引用说:

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 (§6.26.3).



其次,名称绑定(bind)优先级是关于解析已知标识符 x给特定成员pkg.A.B.x如果有多个名为 x 的变量/方法/对象范围内。 ImportIntFooLocalIntFoo名字不一样。

第三,我可以证明单独的名称绑定(bind)优先级不起作用,如下所示:
trait CanFoo[A] {
  def foos(x: A): String
}

object Def {
  implicit object ImportIntFoo extends CanFoo[Int] {
    def foos(x: Int) = "ImportIntFoo:" + x.toString
  }
}

object Main {
  def test(): String = {
    implicit object LocalAnyFoo extends CanFoo[Any] {
      def foos(x: Any) = "LocalAnyFoo:" + x.toString
    }

    // implicit object LocalIntFoo extends CanFoo[Int] {
    //   def foos(x: Int) = "LocalIntFoo:" + x.toString
    // }
    import Def._

    foo(1)
  }

  def foo[A:CanFoo](x: A): String = implicitly[CanFoo[A]].foos(x)
}

println(Main.test)

把这个放在test.scala并运行 scala test.scala ,并打印出 ImportIntFoo:1 .
这是因为静态重载决议(§6.26.3)说更具体的类型获胜。
如果我们假设所有符合条件的隐式值都命名相同,LocalAnyFoo应该屏蔽ImportIntFoo .

相关 :
  • Where does Scala look for implicits?

  • 这是对隐式参数解析的一个很好的总结,但它引用了 Josh 的 nescala 演示而不是规范。他的谈话是促使我研究这个问题的动力。

    编译器实现
  • rankImplicits
  • 最佳答案

    我以博客文章的形式写了自己的答案revisiting implicits without import tax .

    更新 :此外,Martin Odersky 在上述帖子中的评论显示 Scala 2.9.1 的行为为 LocalIntFoo赢得ImportedIntFoo实际上是一个错误。见 implicit parameter precedence again .

  • 1) 通过本地声明、导入、外部范围、继承、可以不带前缀访问的包对象隐含对当前调用范围可见。
  • 2)隐式作用域,它包含所有类型的伴随对象和包对象,它们与我们搜索的隐式类型有某种关系(即类型的包对象、类型本身的伴随对象、其类型构造函数(如果有的话)的它的参数(如果有的话),以及它的父类(super class)型和超特征)。

  • 如果在任一阶段我们发现不止一个隐式的静态重载规则用于解决它。

    更新 2 :当我向 Josh 询问有关无进口税的 Implicits 时,他向我解释说他指的是名称完全相同的implicits 的名称绑定(bind)规则。

    关于Scala:隐式参数解析优先级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8623055/

    相关文章:

    scala - 异常填充子列表

    scala - 在 Spark GraphX 中实现拓扑排序

    makefile - GNU make 在隐式规则中删除目标?

    multithreading - Scala中对象级别的Val和线程安全

    scala - Spark Scala过滤器DataFrame,其中值不在另一个DataFrame中

    scala - 如何从 Scala/Play 2.2 项目中使用 OrientDB?

    c# - 如何创建可以返回 double 或小数的通用 C# 方法?

    scala - 为什么在这种情况下不考虑使用泛型参数的隐式转换?

    scala - 使用 shapeless.Generic 时,如何避免错误 'super constructor cannot be passed a self reference unless parameter is declared by-name' ?

    scala - "illegal cyclic reference"涉及隐式的解释