Предположим, что мы имеем неявный поиск параметров, относящийся только к локальным областям:
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)"?
Edit
Приоритет привязки имени является убедительным аргументом, но есть несколько нерешенных проблем. Во-первых, Scala Справочник по языку говорит:
Если имеется несколько подходящих аргументов, которые соответствуют типу неявных параметров, наиболее конкретный будет выбран с использованием правил статического перегрузочного разрешения (§6.26.3).
Во-вторых, приоритет привязки имени заключается в разрешении известного идентификатора x на конкретный элемент pkg.A.B.x в случае, если в области видится несколько переменных/методов/объектов с именем x. ImportIntFoo и LocalIntFoo не называются одинаковыми.
В-третьих, я могу показать, что приоритет привязки имени не входит в игру следующим образом:
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.
Похожие
Это отличное резюме неявного разрешения параметров, но оно цитирует презентацию Josh nescala вместо спецификации. Его разговор побудил меня взглянуть на это.
Внедрение компилятора