2014-02-07 30 views
2

当试图在Scala中使用更高kinded existentials我碰到以下问题:更高kinded existentials

trait A[H[_]] 
trait Test { 
    val l: A[List] 
    // [error] type mismatch; 
    // [error] found : A[List] 
    // [error] required: A[_[_] <: Any] 
    // [error] Note: List <: Any, but trait A is invariant in type H. 
    // [error] You may wish to define H as +H instead. (SLS 4.5) 
    val x: A[B] forSome { type B[_] } = l 
} 

添加协注解H作为编译器显示的作品。如果我不希望H是协变的,是否有办法解决这个问题?

+0

我刚刚意识到错误在于赋值给x,所以现在我明白为什么你的示例会有意义。 – Blaisorblade

回答

0

的例子中的细微变化给出了一个更实用的错误消息:

scala> l: (A[B] forSome { type B[_] }) 
<console>:10: error: type mismatch; 
found : A[List] 
required: A[_[_] <: Any] 
Note: List <: Any, but trait A is invariant in type H. 
You may wish to define H as +H instead. (SLS 4.5) 
       l: (A[B] forSome { type B[_] }) 
      ^
<console>:10: error: can't existentially abstract over parameterized type B 
       l: (A[B] forSome { type B[_] }) 
      ^

寻找这个错误给我们带来的编译器TODO。

由于存在类型是disappear,根据Odersky的电子邮件,我不认为这个限制会被修复。然而,Martin Odersky的email也提醒我们存在类型等价于抽象类型。因此,如下上面的例子中可以被编码:

scala> trait A { type H[_] } 
defined trait A 

scala> val l: A {type H[X] = List[X]} = null 
l: A{type H[X] = List[X]} = null 

scala> l: A 
res0: A = null 

类型应用在语法上是难看,但转动一个值,一个存在变得微不足道(也以在一个编译器,它是Odersky的的点的一部分实现)。

编码存在的有用之处在于类型成员不必实例化。因此,编码A[_]我们可以这样写:

scala> class A { type T } 
defined class A 

scala> new A 
res1: A = [email protected] 

什么困惑在这里,这并不为对象的工作:

scala> object B { type T } 
<console>:8: error: only classes can have declared but undefined members 
     object B { type T } 
        ^

但最近我接受了一个错误 - 见here的拉要求澄清规格(由Adriaan Moors批准),here为我的错误报告和单线修复编译器(仍在等待审查)。

相关问题