2010-09-04 80 views
24

我需要一些使用traits和結構類型作爲類型參數約束的代碼片段的遞歸結構類型。它工作得很好,但後來我學會了Scala不支持遞歸結構類型。關於Scala中(遞歸)結構類型的有趣觀察

所以有人可以解釋我爲什麼能正常工作:

scala> trait Test[M[A] <: { def map[B](f: A => B) : M[B] } ] {} 
defined trait Test 

,這不:

scala> def test[M[A] <: { def map[B](f: A => B) : M[B] } ] = null 
<console>:5: error: illegal cyclic reference involving type M 
     def test[M[A] <: { def map[B](f: A => B) : M[B] } ] = null 

回答

6

我認爲這是編譯器中的一個小故障。以下代碼表現出與您的初始代碼相同的行爲:

trait Test[M[A] <: { def map: M[A] } ] {} 
def test[M[A] <: { def map: M[A] } ] = null 

它導致編譯時錯誤:'非法循環引用'。

而下面的代碼沒有(即它編譯精細):

type S[M] = { def map: M } 

trait Test[M[A] <: S[M[A]] ] {} 
def test[M[A] <: S[M[A]] ] = null 

唯一的區別是,結構打字經由類型別名應用型在這裏。

+0

實際上,我喜歡使用類型別名的解決方案,它甚至可以用於函數定義。但是你的第一個例子的行爲與我的完全一樣,說Test-trait編譯得很好。但是,如果它使用類型別名,它絕對應該工作而不使用它們?!? – urso 2010-11-18 11:11:32

+0

是的,我認爲這裏有一些不一致:它應該使用類型別名和不使用,或者它不應該工作。這就是爲什麼我認爲這是編譯器中的一個小故障。 – michid 2010-11-18 12:53:17

+0

你有錯誤跟蹤器號碼嗎? – soc 2010-11-23 13:10:22

0

第一代碼片段也拋出錯誤斯卡拉2.7.7final:

scala> trait Test[M[A] <: { def map[B](f: A => B) : M[B] } ] {} 
<console>:4: error: illegal cyclic reference involving type M 
     trait Test[M[A] <: { def map[B](f: A => B) : M[B] } ] {} 
                ^

你使用哪個版本的Scala?

+0

Scala中的工具2.8.1 – tstenner 2010-11-16 19:29:28

+0

我正在使用scala 2.8.0 – urso 2010-11-18 11:10:24