2011-04-06 5 views
10

La signature de la méthode sum sur TraversableOnce est comme suit:Pourquoi cet appel est-il implicitement ambigu?

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

je peux l'utiliser ainsi:

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

Dans ce cas, le compilateur injecte lui-même le Numeric[B], il doit y avoir une valeur implicite non ambiguë de ce type dans la portée. Si j'utilise Predef.implicitly lui injecter moi-même, cela se produit:

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

Pourquoi est-ce ambigu?

Je peux faire l'ambiguïté disparaître soit par

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

Ou

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

Je suppose que cela a quelque chose à voir avec le fait que la somme déclare un nouveau paramètre de type B >: A (clairement est, voir ci-dessous modifier), mais je suis encore confus sur les raisons Someth peut être trouvé sans ambiguïté dans le premier exemple mais pas dans le second?

EDIT-pour aborder un commentaire inepte de sous-sous (ci-dessous)

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 

Ainsi, vous pouvez voir que ce n'est pas le cas que tout appel à est implicitement ambiguë

+1

Il est aussi ambigu que tout appel à implicitement. 'scala> Predef.implicitly : 6: erreur: valeurs implicites ambiguës: les deux méthodes sont conformes dans l'objet Predef de type [A] <: <[A, A] et la méthode stringCanBuildFrom dans l'objet Predef de type => scala. collection.generic.CanBuildFrom [String, Char, String] correspond au type attendu T Predef.implicitly'. Donc, peut-être le sens sous-jacent est quelque chose comme "n'a pas trouvé quelque chose d'implicite approprié ici, s'il vous plaît aider!" – subsub

+0

@subsub - voir mon édition. C'est exactement ce qui se passe; Je demande pourquoi l'appel à implicitement est déduit comme résultant d'un implicite ambigu.S'il existe des valeurs implicites correspondantes dans cope, pourquoi l'appel no-param a-t-il des problèmes similaires? –

+0

Si mon commentaire était inepte, pourquoi avez-vous édité votre question? Eh bien, en voici un autre: 'class Bs [A] (bs: TraversableOnce [A]) {def somme (numbre implicite: Numérique [A]): ​​A = bs.foldLeft (num.zero) (num.plus)} ; (nouveau Bs (1 à 10)) sum (implicitement) ' – subsub

Répondre

5

Court réponse: en raison de B >: A type résultant pour implicitly appel ne peut pas être déduit.

réponse plus longue. Lorsque l'argument défini comme implicit est manquant, le compilateur recherchera la portée actuelle pour toute valeur implicite de type Numeric[B >: Int] et utilisera la plus spécifique - Numeric[Int].

Mais si vous spécifiez l'argument implicitly (un appel au implicitly [T] (implicit e: T) : T), l'argument de type T doit d'abord être résolu. Et Scala Runtime ne parvient pas à le faire.

Il est le même que d'appeler ceci:

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 
      ^
Questions connexes