2012-01-02 18 views
6

我想放寬對特徵類型參數的約束,並將它們強加於證據參數形式的方法。鑑於一些骨骼設置:交換證據參數的類型參數上限

trait State[Repr] 
object Observer { 
    def apply[Repr <: State[Repr]](reader: Reader[Repr]): Observer[Repr] = 
    new Observer[Repr] {} 
} 
trait Observer[A] 
trait Reader [A] 

這工作:

trait StateX[Repr <: StateX[Repr]] extends State[Repr] { 
    protected def reader: Reader[Repr] 
    def observe: Observer[Repr] = Observer(reader) 
} 

這並不:

trait StateY[Repr] extends State[Repr] { 
    protected def reader: Reader[Repr] 
    def observe(implicit ev: Repr <:< State[Repr]): Observer[Repr] = Observer(reader) 
} 

隨着消息"inferred type arguments [Repr] do not conform to method apply's type parameter bounds [Repr <: State[Repr]]"。由於證據ev暗示了這種構象,我不知道如何修復StateY

回答

6

您的問題是,即使形式A <:< B的證據暗示A類型的值可以轉換爲B類型的值,這並不意味着A <: B ......的確,主要原因爲使用類型約束或者一個視圖綁定而不是普通的類型綁定正是因爲這種子類型關係不成立。

因此在StateYRepr <:< State[Repr]約束,不足以滿足約束Repr <: State[Repr]Observerapply方法。考慮到你想放鬆對StateX的類型參數的限制,你唯一的選擇就是相應減弱對方法類型參數的限制。這讓你像下面這樣使用,而不是必然的約束普通型的觀點,

object Observer { 
    def apply[Repr <% State[Repr]](reader : Reader[Repr]) : Observer[Repr] = 
    new Observer[Repr] {} 
} 

或替代,

object Observer { 
    def apply[Repr](reader : Reader[Repr]) 
       (implicit ev : Repr <:< State[Repr]) : Observer[Repr] = 
    new Observer[Repr] {} 
} 

,如果你寧願在整個使用約束。

5

有證據表明Repr可以轉換爲State[Repr]。它沒有說明讀者可以做什麼[Repr]。

給定一個A => B,沒有通用方法(獨立於T)將T [A]轉換爲T [B]。對於協變T,這可能是可能的,但是在語言中沒有這樣的事情。