Предположим, у нас есть неявный поиск параметров, относящийся только к локальным областям:
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)"?
Редактировать :
Приоритет привязки имени является убедительным аргументом, но есть несколько нерешенных проблем.
Во-первых, Справочник по языку 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
.
Относящиеся
Это отличная сводка неявного разрешения параметров, но она цитирует представление Джоша nescala вместо спецификации. Именно его разговор побудил меня заняться этим.
Реализация компилятора