2013-06-24 145 views
5

以下是我真正的問題的簡化版本:斯卡拉:錯誤的隱含參數

class Z[T] 
object E extends Enumeration { 
    implicit val z = new Z[Value] 
    val X, Y = Value 
} 
implicit def f[T : Z] = (getter: T) => 0 
implicit def o[T](v: Option[T])(implicit toInt: T => Int) = 0 
def e: Option[E.Value] = null 
val b: Int = e 

這工作,用b隱式轉換爲O(E)(F(E.z))。但隨着小的變化如下:

​​

它無法找到合適的內含價值E.z雖然有從原來的代碼沒有本質的區別,而手動顯式轉換爲O(E)(F(E.z))仍然有效。

我知道隱式參數的實現還沒有完成,還有很多未解決的問題。如果這是其中之一,我想將其報告給Scala貢獻者。所以我的問題是,a)這真的是一個錯誤? b)如果是這樣,我在哪裏以及如何提交錯誤以便將來修復它?

UPDATE

特拉維斯答案的工作就像一個魅力!順便說,上面的代碼是一個解決方法,我原來的問題:

implicit object E extends Enumeration { val X, Y = Value } 
implicit object F extends Enumeration { val X, Y = Value } 
implicit def f[T <: Enumeration](getter: T#Value)(implicit e: T) = 0 
implicit def o[T](v: Option[T])(implicit toInt: T => Int) = 0 
val b: Int = Some[E.Value](null) 

在這段代碼,情況反過來:它的工作原理與二傳的版本,但不是簡單的環版本。編譯器抱怨說,使用F或F作爲隱式參數是困惑的,儘管使用F實際上並沒有編譯,也沒有意義。我設法得到它的工作做了類似的事情:

implicit def f[S <% T => T, T <: Enumeration](getter: T#Value)(implicit e: T) = 0 

這個工作,雖然我不知能得到它的工作,我還是不明白這個魔術背後的邏輯。

+0

有趣。用'-Xlog-implicits'運行這個函數,看起來'f [T:Z]'中的'T'不會被推斷爲'E.Value'。因此,這是有效的:'val b:Int = o(e)(f [E.Value])'但這不是:'val b:Int = o(e)(f)'。 – gourlaysama

回答

6

您已經遇到Scala的類型推斷系統this limitation的另一個變種。

,編譯器會解決,如果在第一種情況下,它在尋找從普通的舊E.ValueInt的隱式轉換的Tf,但不是在第二,它希望從E.Value => Unit轉換(即Function1[E.Value, Unit])到Int

幸好有像的情況下簡單的解決方法這個,只是使用綁定一個觀點:

implicit def f[F <% T => Unit, T: Z] = (setter: F) => 0 

這將desugar爲類似以下內容:

implicit def f[F, T](implicit st: F <:< (T => Unit), ev: Z[T]) = (setter: F) => 0 

現在,當編譯器要轉換從E.Value => UnitInt它將能夠立即解決FE.Value => Unit然後TE.Value

+0

感謝您的回答,它像一個魅力!但我仍然不明白這個魔法是如何運作的。你可以看看上面的更新並給出解釋嗎?看起來S甚至不需要有意義的類型推斷系統工作..神祕。 –