2014-02-07 62 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爲我的錯誤報告和單線修復編譯器(仍在等待審查)。

相關問題