2011-04-03 65 views
12

我拼命地解決以下幾個:部分應用型參數

trait Access[Res[_]] { def access[C]: Res[C] } 

trait CList[C1, A] extends Access[CList[_, A]] // ?! 

def test[C1, C2, A](c: CList[C1, A]): CList[C2, A] = c.access[C2] 

scalac只是說:"error: illegal cyclic reference involving trait CList"。我怎樣才能編譯?

回答

13

您可能會感興趣的類型lambda表達式,你在你的答案中所使用的部分應用程序實際上是implemented in scalaz 由於代碼的可讀性往往會降低,但他們開始使用類型lambdas代替。所討論的類型可以寫爲

({type λ[α] = CList[α,A]})#λ 

這可以通過在結構類型內的參數化類型λ上創建類型投影來捕獲外部類型參數(在本例中爲A)。

在答案中描述的有關方差的其他問題可以通過使參數Access中的Res協變來解決。

這些改變你的代碼應該是這樣的後:

trait Access[+Res[_]] { def access[C] : Res[C]} 

trait CList[C, +A] extends Access[({type λ[α] = CList[α,A]})#λ] 
+0

謝謝,這看起來好一點。此外,因爲在我的真實情況下CList的類型參數有上限,有一個專用的特質Partial2並不真正有用(我需要爲邊界等添加類型參數) – 2011-04-03 15:25:18

+0

此外,如果您的代碼中經常使用類型lambdas,考慮下面的編譯器插件: https://github.com/non/kind-projector – 2017-11-12 10:49:23

2

google搜索「部分類型的應用程序」,我發現這個解決方案張貼詹姆斯IRY階辯論名單(http://scala-programming-language.1934581.n4.nabble.com/Partial-type-inference-td2007311.html;適合於使該ARG順序被改變):

type Partial2[T[_,_], B] = { 
    type Apply[A] = T[A,B] 
} 
trait CList[C1, A] extends Access[Partial2[CList, A]#Apply] 

奶酪路易絲,這是真的只有在2011年斯卡拉這樣做的方法?!

編輯:

這種失敗,協方差A:。, - (

trait Access[Res[_]] { def access[C]: Res[C] } 

type Partial2[T[_,_], B] = { 
    type Apply[A] = T[A,B] 
} 
trait CList[C1, +A] extends Access[Partial2[CList, A]#Apply] 

"covariant type A occurs in invariant position" 
0

我知道這是一個非常古老的問題,但無論如何:

trait AnyAccess { 
    type Res[X] 
    def access[Z]: Res[Z] 
} 

trait AnyCList extends AnyAccess { me => 
    type C 
    type A 
    // this could be a subtype bound instead, if needed 
    type Res[X] = AnyCList { type C = X; type A = me.A } 
} 
case object AnyCList { 
    type of[C0, +A0] = AnyCList { type C = C0; type A <: A0 } 
} 

case object buh { 

    def test[C1, C2, A](c: AnyCList.of[C1, A]): AnyCList.of[C2, A] = c.access[C2] 
}