Может ли Scala замечать различия между типами, зависящими от пути? - PullRequest
4 голосов
/ 22 декабря 2011

Иногда в Scala я обнаруживаю несоответствия типов, связанные с типами, зависящими от пути, но я легко могу предположить, что на самом деле типы совпадают. Вот простой пример:

trait Foo { trait Bar }

object Main extends App {
  val foo1 = new Foo { }
  val foo2 = foo1

  def turkle(x: foo1.Bar) {}

  turkle(new foo2.Bar {})
}

, что дает: "несоответствие типов; найдено: java.lang.Object с Main.foo2.Bar требуется: Main.foo1.Bar".

Теперь, конечно, пути Main.foo1.Bar и Main.foo2.Bar должны совпадать, так как мы написали val foo2 = foo1. Мы можем это проверить, изменив последнюю строку на

turkle((new foo2.Bar {}).asInstanceOf[foo1.Bar])

, который компилируется и запускается без исключения.

Может ли Scala автоматически выполнять рассуждения подобным образом? Если так, как я могу это сделать?

(А если нет, есть ли перспективы для расширения системы типов в этом направлении?)

Я отмечу, что иногда Scala действительно выполняет такие рассуждения. Предположим, я изменил trait Foo на object Foo:

object Foo { trait Bar }

object Main extends App {
  val foo1 = Foo
  val foo2 = foo1

  def turkle(x: foo1.Bar) {}

  turkle(new foo2.Bar {})
}

Теперь все компилируется нормально: каким-то образом в Scala выяснилось, что Main.foo1.Bar и Main.foo2.Bar действительно совпадают с Foo.Bar.

1 Ответ

5 голосов
/ 23 декабря 2011

Юлиан Драгос дал ответ, который вам нужен в недавнем вопросе.Короткая версия заключается в том, что компилятор не выполняет анализ потока, поэтому в вашем первом примере он не может сказать, что foo1.Bar и foo2.Bar относятся к одному и тому же типу, поскольку foo1 и foo2 имеют тип Foo.Но во втором примере foo1 выводится как синглтон-тип Foo.type (подтип Foo), поэтому все работает как положено.

Вы можете заставить свой первый пример работать, объявив foo2 как синглтон-типиз foo1:

val foo2:foo1.type = foo1

См. раздел 3.2.1 Спецификации языка Scala 2.9 для справки.

...