Почему эта циклическая ссылка с незаконченным типом?
Следующий псевдо- Scala дает ошибку "незаконной циклической ссылки":
trait GenT[A]
trait T extends GenT[T#A] {
type A
}
Вопросы. Почему это незаконно? Есть ли фундаментальная проблема со звуком, или это ограничение системы типа Scala? Есть ли работа?
Мое намерение состоит в создании признака T
с членом типа A
, который может быть отменен по требованию параметру типа с помощью супер-признака GenT[A]
. Одним из приложений может быть выражение ограничений, например
def foo[A, S1 <: GenT[A], S2 <: GenT[A]] ...
Это может быть использовано как def foo[S1 <: T, S2 <:T] ...
с ограничением S1#A == S2#A
.
Если бы эта техника была возможна, она также могла бы помочь в вопросе: Как специализироваться на проекции типа в Scala?
Примечание. Я мог бы использовать GenT
вместо T
всюду, но я стараюсь избегать этого, потому что это заставит множество параметров типа распространяться по всему моему "заразительному" коду.
Два приведенных ниже вопроса кажутся похожими, но относятся к различному типу циклической ссылки:
Ответы
Ответ 1
В вашем первом примере вы можете разбить цикл, введя вспомогательный тип между GenT [A] и T,
trait GenT[A]
trait TAux { type A }
trait T extends TAux with GenT[TAux#A]
Но из вашего мотивирующего примера я не думаю, что вам нужно идти по этому маршруту. Ограничение, за которым вы после, может быть выражено напрямую с помощью уточнения,
trait T { type A }
def foo[A0, S1 <: T { type A = A0 }, S2 <: T { type A = A0 }] ...
Также имейте в виду, что вы можете нарисовать элемент типа как параметр типа с помощью псевдонима типа,
trait T { type A }
type TParam[A0] = T { type A = A0 }
def foo[A0, S1 <: TParam[A0], S2 <: TParam[A0]] ...