2011-04-06 66 views
10

sum方法對TraversableOnce簽名是如下:爲什麼這個調用隱含地含糊不清?

def sum[B >: A](implicit num: Numeric[B]): B = foldLeft(num.zero)(num.plus) 

我因此可以使用它:

scala> (1 to 10).sum 
res0: Int = 55 

在這種情況下,編譯器被注入Numeric[B]本身,所以必須有範圍內的這種類型的明確的隱含值。如果我使用Predef.implicitly注入它自己,這種情況發生:

scala> (1 to 10).sum(implicitly) 
<console>:6: error: ambiguous implicit values: 
both method conforms in object Predef of type [A]<:<[A,A] 
and method stringCanBuildFrom in object Predef of type => scala.collection.generic.CanBuildFrom[String,Char,String] 
match expected type T 
    (1 to 10).sum(implicitly) 
       ^

這是爲什麼曖昧?

我可以使模糊消失或者通過

scala> (1 to 10).sum(implicitly[Numeric[Int]]) 
res2: Int = 55 

或者

scala> (1 to 10).sum[Int](implicitly) 
res3: Int = 55 

我相信,這事做的事實和聲明瞭一個新的類型參數B >: A顯然是,見下面編輯),但我仍然爲什麼有些困惑在第一個例子中可以明確地發現ing,但不是第二個?

編輯 - 解決subsub的空洞的評論(下同)

scala> class As[A](as : A*) { 
| def sum(implicit num : Numeric[A]) : A = as.foldLeft(num.zero)(num.plus) 
| } 
defined class As 

scala> (new As(1, 2, 3, 4)).sum 
res0: Int = 10 

scala> (new As(1, 2, 3, 4)).sum(implicitly) 
res1: Int = 10 

所以,你可以看到,它不是任何呼叫隱式是模糊

+1

這是模棱兩可的任何調用隱式。 'scala> Predef.implicitly :6:error:含糊隱含值: 這兩種方法都符合類型爲[A,A] <:[[A,A] 的對象Predef和類型爲>> scala的對象Predef中的方法stringCanBuildFrom。 collection.generic.CanBuildFrom [String,Char,String] 匹配預期類型T Predef.implicitly'。所以可能的底層含義是「沒有找到任何合適的隱含的東西在這裏,請幫助!」 – subsub 2011-04-06 12:26:55

+0

@subsub - 請參閱我的編輯。這正是發生了什麼;我在問爲什麼隱含的調用被推斷爲導致模棱兩可的隱含。如果在應付方式中存在匹配的隱含值,爲什麼no-param調用會有類似的問題? – 2011-04-06 13:27:04

+0

如果我的評論是蠢話,你爲什麼編輯你的問題? (bs:TraversableOnce [A]){def sum(implicit num:Numeric [A]):A = bs.foldLeft(num.zero)(num.plus)}這是另一個: ; (新Bs(1到10))。sum(隱含地)' – subsub 2011-04-06 14:00:29

回答

5

短的情況下回答:因爲B >: A產生的類型爲implicitly,調用無法推斷。

較長的答案。當缺少定義爲implicit的參數時,編譯器將在當前作用域中搜索任何類型爲Numeric[B >: Int]的隱式值,並將使用最具體的 - Numeric[Int]

但是,如果您指定參數爲implicitly(調用implicitly [T] (implicit e: T) : T),首先必須解析類型參數T。而scala運行時顯然沒有這樣做。

它是與調用此:

scala> var f = implicitly 
<console>:5: error: ambiguous implicit values: 
both method conforms in object Predef of type [A]<:<[A,A] 
and method stringCanBuildFrom in object Predef of type =>  scala.collection.generic.CanBuildFrom[String,Char,String] 
match expected type T 
     var f = implicitly 
      ^