2015-02-07 77 views
6

以下代碼:路徑依賴類型 - 以下代碼有什麼問題?

trait Foo { 
    type T 
    val x: T 
} 

trait Bar { 
    type F <: Foo { type T <: F } 
} 

class C[B <: Bar](val f: B#F) { 
    val x: f.T = f.x 
}  

由Scala編譯器(2.11.5)用下面的錯誤消息被拒絕:

error: type mismatch; 
found : C.this.f.x.type (with underlying type C.this.f.T) 
required: this.T 
     val x: f.T = f.x 
       ^

如果省略了明確的類型聲明,類型是正確地推斷根據來自導電型測量儀相的輸出:

private[this] val x: C.this.f.T = C.this.f.x; 
<stable> <accessor> def x: C.this.f.T = C.this.x 

問題也消失如果F內側結合的被改變爲一個類型爲不是Bar成員,即

type F <: Foo { type T <: Foo } 

正常工作。

這是一個錯誤?或者我的一些根本的誤解?或者一些神祕的功能?

回答

2

沒有一個明確的答案,但一些觀察...

讓我們先來看看有什麼不工作:

class C[B <: Foo](val f: B) { 
    val x: f.T = f.x 
} 

所以編譯器失去你時使用的值f類型的投射。如果「修復」是投影,它也似乎工作:

class D[B <: Bar](val f: B#F) { 
    val g: Foo = f 
    val x: g.T = g.x 
} 

我早就跟F-界類型掙扎着,直到我讓他們「水緊」。有一些關於類型參數與類型成員使前者工作。例如:

trait FooRec[F <: FooRec[F]] extends Foo { 
    type T = F 
} 

class E[F <: FooRec[F]](val f: F) { 
    val x: f.T = f.x 
} 

最後,您還可以通過將它作爲一個類型參數修正Bar的類型成員:

class G[F1 <: Foo { type T = F1 }, B <: Bar { type F = F1 }](val f: B#F) { 
    val x: f.T = f.x 
} 

相若方式,如果你已經修復型的Bar定義,它的工作原理:

trait Baz { 
    type F <: Foo { type T = F } // stable recursion 
} 

class H[B <: Baz](val f: B#F) { 
    val x: f.T = f.x 
} 

所以在你的原始定義和應用程序有上限似乎是不夠的。也許你可以證明編譯器是正確的關於它的拒絕,但我不知道如何...

+0

謝謝你的興趣。有趣的是,如果沒有這個聲明,編譯器會像問題中提到的那樣將'x'的類型作爲'f.T'本身來引用。而且,它允許在使用'Foo'和'C'的代碼中使用它。所以唯一的問題是明確的聲明 - 因此我的困惑。 – 2015-02-08 23:43:42