2015-04-16 31 views
2

我有三F-綁定類型AB & C,其中BA參數化的,並且CB參數化(並因此也通過A)。我可以實例化AB,但是當我嘗試實例化C時,編譯器無法推斷出這些類型。如果我明確地給出它的類型,一切都可行 - 但這些類型丟失似乎相當愚蠢(這是由於類型擦除?)。構建三級深F-綁定類型

sealed trait A[AA <: A[AA]] { 
    self => 
    val data: String 
} 

case class AInst(data: String) extends A[AInst] 

sealed trait B[BB <: B[BB, AA], AA <: A[AA]] { 
    self: BB => 
    val content: AA 
} 

case class BInst[AA <: A[AA]](content: AA) extends B[BInst[AA], AA] 

sealed trait C[CC <: C[CC, BB, AA], BB <: B[BB, AA], AA <: A[AA]] { 
    self: CC => 
    val content: BB 
} 

case class CInst[BB <: B[BB, AA], AA <: A[AA]](content: BB) 
    extends C[CInst[BB, AA], BB, AA] 

val a1 = new AInst("A1") 
val b1 = BInst(a1) 
val c1 = CInst[BInst[AInst],AInst](b1) 

有一個變通,在那裏我沒有爲CInst專門指定的類型?

我目前使用類型參數化來實現F-Bounds,但是會切換到抽象類型成員來解決這個問題嗎?上課怎麼樣?

+0

我在這裏的例子:https://stackoverflow.com/questions/1154571/scala-abstract-types-vs-generics/10891994#10891994 – ayvango

回答

1

怎麼樣:

... //A,AInst,B,BInst without changes 

sealed trait C[CC <: C[CC, BB, AA], BB <: B[BB, AA], AA <: A[AA]] { 
    self: CC => 
    val content: B[BB, AA] //`B[BB, AA]` instead of `BB` 
} 

case class CInst[BB <: B[BB, AA], AA <: A[AA]](content: B[BB,AA]) extends C[CInst[BB, AA], BB, AA] 

用法:

scala> val a1 = new AInst("A1") 
a1: AInst = AInst(A1) 

scala> val b1 = BInst(a1) 
b1: BInst[AInst] = BInst(AInst(A1)) 

scala> val c1 = CInst(b1) 
c1: CInst[BInst[AInst],AInst] = CInst(BInst(AInst(A1))) 

這並不像看到的BBBInst[AA <: A[AA]]編譯器之前的工作,所以我B[BB,AA]剛剛解禁BBB[BInst[AInst], AInst]

P.S.對於類型成員,您仍然推動以某種方式將類型傳遞給您的案例類,所以沒有太大區別。

+0

太好了,謝謝!我非常接近...類型定義變得稍微笨拙,我不知道這是否也是代碼異味的一種形式。 – Karalga

+0

這取決於你如何看待它們:)我將它們視爲編譯時'def's [像這裏](http://stackoverflow.com/a/29470018/1809978)。但是編譯器類型推理可能不那麼清楚,實際上它非常依賴於你的領域邏輯,你可能真的不需要它們 – dk14