2011-07-22 58 views
3

为什么这个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 {类型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] 

虽然这里的类型精化似乎并没有添加任何新的信息。 (也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作为实施特质GenFoo明显的参数A0,这可以直接专业化。我希望将Miles Sabin的答案应用于Why is this cyclic reference with a type projection illegal?,但我遇到了这种一致性错误。

+0

你有没有试过-explaintypes? –

+0

感谢您的指针。我更新了问题以包含-explaintypes的输出。 –

回答

1

这似乎是答案:

小号专业A型?

问题有关专门来自这里:T { type A = A0 }。这是类型Ttype 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] 

然后再编译,因为SFoo[S <: T]符合在GenFoo[A0, S <: T]S

在您的例子编译器知道ST一个亚型,因此具有确定的type A,但它不来的地步,它可以验证在SAS#A

+0

谢谢。我更新了问题以包含此信息。 –