为什么这个电话隐含含糊不清?

oxb*_*kes 11 scala implicit

sum方法的签名TraversableOnce如下:

def sum[B >: A](implicit num: Numeric[B]): B = foldLeft(num.zero)(num.plus)
Run Code Online (Sandbox Code Playgroud)

我可以这样使用它:

scala> (1 to 10).sum
res0: Int = 55
Run Code Online (Sandbox Code Playgroud)

在这种情况下,编译器会注入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)
                 ^
Run Code Online (Sandbox Code Playgroud)

为什么这个含糊不清?

我可以使模糊性消失

scala> (1 to 10).sum(implicitly[Numeric[Int]])
res2: Int = 55
Run Code Online (Sandbox Code Playgroud)

要么

scala> (1 to 10).sum[Int](implicitly)
res3: Int = 55
Run Code Online (Sandbox Code Playgroud)

我认为这与sum声明一个新的类型参数B >: A(显然是,见下面的编辑)这一事实有关,但我仍然感到困惑的是为什么在第一个例子中可以明确地找到某些东西而不是第二个例子?

编辑 - 解决子课程的愚蠢评论(下)

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
Run Code Online (Sandbox Code Playgroud)

所以,你可以看到隐含的任何调用都不是模糊的

Nik*_*sov 6

简答:由于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
               ^
Run Code Online (Sandbox Code Playgroud)