2011-07-22 5 views
3

Почему этот код Scala не работает с typecheck?Почему аргументы типа не соответствуют уточнению типа?

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 {типа A = A0}]". Есть ли работа?

Редактировать: Как было указано, ошибка соответствия проистекает из неявки S <: T{type A = S#A}. Daniel Собрал указал на -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] 

хотя тип уточнения здесь, кажется, не добавить новую информацию. (Смотрите также Why is this cyclic reference with a type projection illegal?)

Моя мотивация создать признак Foo[S <: T], который специализируется на S#A, как: How to specialize on a type projection in Scala? Для того, чтобы получить эту работу, я пытаюсь поверхности S#A в качестве явного параметра A0 в реализации признака GenFoo, которые могут быть специализированы непосредственно. Я надеялся применить идею уточнения типа от ответа Майлза Сабина до Why is this cyclic reference with a type projection illegal?, но я столкнулся с этой ошибкой соответствия.

+0

Вы пробовали -explaintypes? –

+0

Спасибо за указатель. Я обновил вопрос, чтобы включить вывод из -explaintypes. –

ответ

1

Это, кажется, ответ:

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

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

Ответ на этот вопрос: нет ограничений на S, чтобы он был специализированным.

+0

Удивительно, что существует разница между 'S <: T' и' S <: T {type A = S # A} '. Хотя последний специализирован, кажется, что эта специализация не добавляет никаких дополнительных ограничений на 'S'. (Может быть, намек на то, что последний дает недопустимую циклическую ошибку ссылки, если вы пытаетесь использовать его напрямую.) Возможно, я неправильно понимаю смысл типов, но кажется, что это практическое, а не фундаментальное ограничение в типе Scala система? –

1

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

+0

Но в этом случае 'A0 = S # A', поэтому я бы ожидал' S <: T {type A = S # A} ' –

1

Я не эксперт по этой теме, я просто играл с вашим кодом и выяснил, что проблема не в части 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.

+0

Спасибо. Я обновил вопрос, чтобы включить эту информацию. –