Почему эти аргументы типа не соответствуют уточнению типа?

Почему этот код Scala не проходит проверку типов?

trait T { type A }
trait GenFoo[A0, S <: T { type A = A0 }]
trait Foo[S <: T] extends GenFoo[S#A, S]

Я не понимаю, почему «аргументы типа [S#A,S] не соответствуют границам параметра типа типажей GenFoo [A0,S ‹: T{type A = A0}]». Есть ли обходной путь?

Изменить. Как уже отмечалось, ошибка соответствия связана с невозможностью проверки S <: T{type A = S#A}. Даниэль Собрал указал на -explaintypes, что говорит нам:

S <: T{type A = S#A}?
  S <: T?
  true
  S specializes type A?
    this.A = this.A?
      S = this.type?
      false
    false
  false
false

Я не уверен, как это интерпретировать.

Обратите внимание, что мы получим недопустимую циклическую ссылку, если попытаемся определить

trait Foo[S <: T { type A = S#A } ] extends GenFoo[S#A, S]

хотя уточнение типа здесь, кажется, не добавляет никакой новой информации. (См. также Почему эта циклическая ссылка с проекцией типа незаконно?)

Моя мотивация — создать трейт Foo[S <: T], который специализируется на S#A, например: Как специализироваться на проекции типов в Scala? Чтобы заставить это работать, я пытаюсь представить S#A как явный параметр A0 в свойстве реализации GenFoo, который можно специализировать напрямую. Я надеялся применить идею уточнения типа из ответа Майлза Сабина на Почему эта циклическая ссылка с проекцией типа недопустима? но я сталкиваюсь с этой ошибкой соответствия.


person Kipton Barros    schedule 22.07.2011    source источник
comment
Вы пробовали -explaintypes?   -  person Daniel C. Sobral    schedule 23.07.2011
comment
Спасибо за указатель. Я обновил вопрос, включив вывод из -explaintypes.   -  person Kipton Barros    schedule 23.07.2011


Ответы (3)


Кажется, это ответ:

S специализируется на типе А?

Вопрос о специализации взят отсюда: T { type A = A0 }. Это тип T с type A специализированным, что означает, что он более ограничен, чем исходный T.

Ответ на этот вопрос — нет — для S нет никаких ограничений по его специализации.

person Daniel C. Sobral    schedule 25.07.2011
comment
Меня удивило, что между S <: T и S <: T { type A = S#A } есть разница. Хотя последний является специализированным, кажется, что эта специализация не накладывает дополнительных ограничений на S. (Может быть, это намек на то, что последний дает недопустимую ошибку циклической ссылки, если кто-то пытается использовать его напрямую.) Возможно, я неправильно понимаю значение типов, но кажется, что это практическое, а не фундаментальное ограничение типа Scala. система? - person Kipton Barros; 26.07.2011

Чтобы соответствовать ограничениям типа, S должен быть подтипом T { type A = A0 }, но это только подтип T.

person Kim Stebel    schedule 22.07.2011
comment
Но в данном случае A0 = S#A, поэтому я ожидаю S <: T { type A = S#A } - person Kipton Barros; 23.07.2011

Я не эксперт в этой теме, просто поигрался с вашим кодом и выяснил, что проблема не в части S#A, а в части S.

Если написать такой код:

trait T { type A }
trait GenFoo[A0, S <: T] // the { type A = A0 } part is not there anymore
trait Foo[S <: T] extends GenFoo[S#A, S]

затем он компилируется, потому что S в Foo[S <: T] соответствует S в GenFoo[A0, S <: T].

В вашем примере компилятор знает, что S является подтипом T и, следовательно, имеет определенный type A, но не доходит до того, что он может проверить, что A в S является S#A.

person Community    schedule 22.07.2011