2011-04-06 29 views
10

La firma del método sum en TraversableOnce es como sigue:¿Por qué esta llamada es implícitamente ambigua?

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

I pueden usar así:

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

En este caso, el compilador está inyectando el Numeric[B] sí mismo, así que debe haber un valor implícito inequívoco de este tipo en el alcance. Si uso Predef.implicitly para inyectarla a mí mismo, esto sucede:

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) 
       ^

¿Por qué es ambigua?

Puedo hacer la ambigüedad desaparece, ya sea por

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

O

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

supongo que esto tiene algo que ver con el hecho de que la suma declara un nuevo parámetro de tipo B >: A (es claramente, vea abajo edite), pero todavía estoy confundido acerca de por qué algo ing se puede encontrar inequívocamente en el primer ejemplo pero no en el segundo?

EDITAR - a Dirección Comentario inane de subsub (continuación)

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 

Por lo tanto, se puede ver que no es el caso de que cualquier llamada a implícitamente es ambigua

+1

es tan ambigua como cualquier llamada a la implícita. 'scala> Predef.implicitly : 6: error: valores implícitos ambiguos: Ambos métodos se ajustan en el objeto Predef del tipo [A] <: <[A, A] y el método stringCanBuildFrom en el objeto Predef de tipo => scala. collection.generic.CanBuildFrom [String, Char, String] coincide con el tipo esperado T Predef.implicitly'. Así que posiblemente el significado subyacente sea algo así como "no encontré ninguna cosa implícita adecuada aquí, ¡por favor ayuda!" – subsub

+0

@subsub - ver mi edición. Eso es exactamente lo que está pasando; Me estoy preguntando por qué la llamada implícitamente se infiere como resultado de un implícito ambiguo.Si hay valores implícitos coincidentes en Cope, ¿por qué la llamada no-param tiene problemas similares? –

+0

si mi comentario fue inane ¿por qué editó su pregunta? Bueno, aquí hay otro: 'clase Bs [A] (bs: TraversableOnce [A]) {def sum (num implícito: Numérico [A]): ​​A = bs.foldLeft (num.zero) (num.plus)} ; (nuevos Bs (1 a 10)). sum (implícitamente) ' – subsub

Respuesta

5

corto respuesta: Debido a B >: A tipo resultante para implicitly no se puede inferir la llamada.

Respuesta larga. Cuando falta el argumento definido como implicit, el compilador buscará en el alcance actual cualquier valor implícito del tipo Numeric[B >: Int] y usará el más específico - Numeric[Int].

Pero si especifica el argumento como implicitly (una llamada al implicitly [T] (implicit e: T) : T) primero debe resolverse el argumento de tipo T. Y Scala Runtime claramente no lo hace.

Es el mismo que llamar a esto:

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 
      ^
Cuestiones relacionadas