Scala: неявный приоритет разрешения параметров

Предположим, у нас есть неявный поиск параметров, относящийся только к локальным областям действия:

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.ABx в случае наличия нескольких переменных / методов / объектов с именем 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 Джоша вместо спецификации. Его выступление побудило меня заняться этим.

Реализация компилятора

15
задан Community 23 May 2017 в 11:53
поделиться