The signature of the sum
method on TraversableOnce
is as follows:
def sum[B >: A](implicit num: Numeric[B]): B = foldLeft(num.zero)(num.plus)
I can use it thus:
scala> (1 to 10).sum
res0: Int = 55
In this case, the compiler is injecting the Numeric[B]
itself, so there must be an unambiguous implicit value of this type in scope. If I use Predef.implicitly
to inject it myself, this happens:
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)
^
Why is this ambiguous?
I can make the ambiguity disappear either by
scala> (1 to 10).sum(implicitly[Numeric[Int]])
res2: Int = 55
Or
scala> (1 to 10).sum[Int](implicitly)
res3: Int = 55
I presume that this has something to do with the fact that sum declares a new type parameter B >: A
(it clearly is, see below edit), but I'm still confused about why something can be unambiguously found in the first example but not the second?
EDIT - to address subsub's inane comment (below)
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
So, you can see that it is not the case that any call to implicitly is ambiguous