2011-12-12 62 views
4

即使顯式調用該函數,爲什麼下面的隱式轉換不起作用?爲什麼在顯式轉換工作時,此Scala隱式轉換失敗?

scala> implicit def view[A, C](xs: C)(implicit ev: C <:< Iterable[A]) = new { def bar = 0 } 
view: [A, C](xs: C)(implicit ev: <:<[C,scala.collection.immutable.Iterable[A]])java.lang.Object{def bar: Int} 

scala> List(1) bar 
<console>:147: error: Cannot prove that List[Int] <:< scala.collection.immutable.Iterable[A]. 
       List(1) bar 
       ^

scala> view(List(1)) bar 
res37: Int = 0 
+0

我把你的代碼放到scala eclipse IDE中,並且它失敗了三次 - 值視圖不是AnyRef的成員(def bar:Int)注意:隱式視圖在這裏不適用;標識符預期但'['找到;未找到:輸入錯誤。 – 2015-05-07 09:38:20

回答

0

我真的不回答你的問題(即我回答到「我怎麼使這項工作」,而不是在「爲什麼它不工作」);無論如何希望這會幫助別人取得一些進展的答案。

因此......在第一種情況下,如果C是List [Int],編譯器無法正確推斷出A是一個Int。老實說,我更驚訝的是,明確地通過列表實際上是有效的,因爲A和C之間的關係非常間接(你有一個A和一個C,因爲C是Iterable [A]的子類型,並且因爲C是一個List [ Int],那麼A必須是一個Int;不是一個非常直接的推論......)。

你可以把它通過更明確的關於C和A之間的關係,像這樣的工作:

scala> implicit def view[A, C[A]](xs: C[A])(implicit ev: C[A] <:< Iterable[A]) = 
     new { def bar = 0 } 
view: [A, C[A]](xs: C[A])(implicit ev: <:<[C[A],Iterable[A]])java.lang.Object{def bar: Int} 

scala> List(1) bar 
res0: Int = 0 

或(因爲你不使用A):

scala> implicit def view[C](xs: C)(implicit ev: C <:< Iterable[_]) = 
     new { def bar = 0 } 

scala> List(1) bar 
res1: Int = 0 
+0

但是,這將xs的類型限制爲應用的一元類型構造函數;所有其他類型不包括在內。在http://suereth.blogspot.com/2011/06/generic-quicksort-in-scala.html上查看解釋。 – Yang

+0

哇,那是一些黑帶級別的類型fu!我發現我的「解決方案」實際上是打破了您的方法的精心構建的類型簽名,但我需要一些時間來吸收您發送的其他帖子......但是,FWIW,我的第二個視圖定義仍然有效與非一元類型的構造函數。我已經用'class Foo(t:List [Int])擴展Iterable [Int] {def iterator:Iterator [Int] = t.iterator}'測試了它,它沒有類型參數,並且'(new Foo(List (1)))。查看酒吧的作品。 –

0

簡單地說,如錯誤消息所示,它不能推斷出A。編譯器沒有任何信息可以用來推斷什麼是A,所以它必須假設它可以是任何東西。

你可能會反駁說,它可以推斷C <:< Iterable[A]A,但會變成這個問題上發揮得淋漓盡致:而不是使用<:<檢查約束,它將使用約束來推斷A類型!這種邏輯不健全。

+0

但是對於大多數類似統一的證明者,信息必須在兩個方向上流動,並在中間解決。考慮明確的調用,它可以工作並推斷出「A」。 – Yang