2014-10-27 138 views
1

我想表達類似的約束:斯卡拉類型平等和路徑依賴的類型

in a method def run[A, B](...), B must be equal to A#SomeInner

這裏是我的示例代碼:

trait Wrapper { 
    type Implementation 
    implicit val instance: Data[Implementation] 
} 

trait Data[A] { 
    def create : A 
} 

object DataInstances { 
    implicit object IntData extends Data[Int] { def create = 0} 
    implicit object StringData extends Data[String] { def create = "<empty>"} 
    implicit object FloatData extends Data[Float] { def create = 0.5F} 
} 


import DataInstances._ 

object IntWrapper extends Wrapper { type Implementation = Int; implicit val instance = IntData } 
object StringWrapper extends Wrapper { type Implementation = String; implicit val instance = StringData} 
object FloatWrapper extends Wrapper { type Implementation = Float; implicit val instance = FloatData} 



object Test extends App { 

    def run[W <: Wrapper, D](wrapper: W)(implicit data: Data[D], ev: D =:= W#Implementation) : D = { 
    data.create 
    } 

    run(StringWrapper) 
} 

,在這裏我得到一個編譯錯誤:

Error:(31, 6) ambiguous implicit values: 
       both object IntData in object DataInstances of type DataInstances.IntData.type 
       and object StringData in object DataInstances of type DataInstances.StringData.type 
       match expected type Data[D] 
       run(StringWrapper) 
       ^

你能解釋我爲什麼編譯器發現它曖昧? 從我能說的(以及我試圖表達的)是,當我通過StringWrapper時,根據類型相等證據,D唯一可能的值將是String,因此data的唯一可能值將是StringData

但很明顯,編譯器並不這麼認爲:)

什麼是正確表達這種約束的方式嗎?

回答

2

我沒有看到在方法運行中引入類型D的原因。沒有這個方法簽名看起來簡單,編譯成功

def run[W <: Wrapper](wrapper: W)(implicit data: Data[W#Implementation]) : W#Implementation = { 
    data.create 
} 

+++

順便說一句,如果你改變你原來的方法implicits的順序它將編譯過,看起來像「EV」幫助「類型 - 綁定「數據的隱式分辨率

def run[W <: Wrapper, D](wrapper: W)(implicit ev: D =:= W#Implementation, data: Data[D]) : D = { 
    data.create 
    } 
+0

當然!非常感謝!我很愚蠢,我甚至在另一個地方做第一名:)至於第二,是的,似乎這個命令很重要......再次感謝! – 2014-10-27 05:04:58