2012-01-29 2 views
2

Я пытаюсь ниже со Scala 2.10.0-M1:типа при использовании зависимых типов методов и проекции типа

trait Container { 
    type X 
} 

class Test[C <: Container](val c: C) { 
    def foo(x: c.X): C#X = x // this compiles fine 
    def bar(x: C#X): c.X = x // this does not compile 
} 

Проблема состоит в том же, при использовании этой формы:

def bar[C <: Container](c: C)(x: C#X): c.X = x 

Я действительно не понимаю, почему foo компилируется в то время как bar нет.

Я считаю, что c.X и C#X здесь должны быть одинаковыми.

Кроме того, я не понимаю, сообщение об ошибке:

[error] found : x.type (with underlying type C#X) 
[error] required: Test.this.c.X 
[error] possible cause: missing arguments for method or constructor 
[error] def bar(x: C#X): c.X = x // this does not compile 

Любая идея?

+0

Это был в частности, проблема с дизайном, когда я хотел получить тип из зависимого от пути типа. Я создал [другой вопрос] (http://stackoverflow.com/questions/9065343/exposing-a-path-dependent-type-coming-from-a-singleton-type) для этого. – betehess

ответ

7

C#X означает X от любых C. c.X означает X от вашего C, а именно c. Последнее гораздо более конкретное!

Например, если X является счетом и c является конкретным клиентом, c.X означает, что метод принимает только счета от (для, предположительно) клиента c. C#X означает, что он принимает любой счет от любого клиента. Если вы хотите, чтобы клиенты получали только собственные счета (по крайней мере, по умолчанию), первое - это то, что вы хотите.

2

c.X и C#X определенно не совпадают - если бы они были, то почему бы и то, и другое существовать?

Рассмотрите случай, когда у вас есть a и b, разные экземпляры C. По определению a.X и b.X отличаются, но оба являются C#X.

3

@Rex дал хорошее объяснение того, что не так. Вот как вы можете это исправить ...

Если это разумно, чтобы иметь возможность вернуть x в результате типа c.X (то есть. Значение в X типа конкретного c передается в качестве аргумента, то вы можете затянуть это типа в качестве аргумента,

def bar[C <: Container](c: C)(x: c.X): c.X = x 

Теперь бар будет принимать только значения типа X, которые по отношению к определенному значению c. Если это не работает для вас на сайтах вызова на панели, то вам нужно будет для доработки вашей конструкции.