En essayant de répondre à this question, je suis venu avec le code suivant:résolution Scala de plusieurs paramètres implicites
case class Monkey(bananas: Int)
case class Tree(rings: Int)
case class Duck(quacks: Seq[String])
implicit class IntLike(val x : Int) extends AnyVal
implicit def monkey2Age(monkey: Monkey): IntLike = monkey.bananas/1000
implicit def tree2Age(tree: Tree): IntLike = tree.rings
implicit def duck2Age(duck: Duck): IntLike = duck.quacks.size/100000
def purchaseCandles[A <% IntLike]()(implicit age : A) = {
val asAge : IntLike = age
println(s"I'm going to buy $asAge candles!")
}
{
implicit val guest = Tree(50)
purchaseCandles()
}
Notez que le IntLike
est seulement là pour me convaincre ce n'était pas un problème axé sur Int
.
Cela semble être une utilisation assez standard, si mauvaise, d'implicits, et je m'attendais à ce qu'il fonctionne bien. Cependant, sur l'appel purchaseCandles()
REPL donne l'erreur suivante:
error: ambiguous implicit values: both value StringCanBuildFrom in object Predef of type => scala.collection.generic.CanBuildFrom[String,Char,String] and value guest of type Tree match expected type A
Je ne peux pas pour la vie de me voir comment cela est le cas. A est lié à avoir une vue liée à IntLike
, un type que je viens d'inventer. Le REPL confirme qu'il n'y a pas de vue implicite disponible:
scala> implicitly[Tree => IntLike]
res14: Tree => IntLike = function1
mais
scala> implicitly[scala.collection.generic.CanBuildFrom[String, Char, String] => IntLike]
:18: error: No implicit view available from scala.collection.generic.CanBuildFrom[String,Char,String] => IntLike.
Alors, comment peut StringCanBuildFrom
être d'un type approprié? Le compilateur est-il capable de résoudre les implicites dépendants multiples, et si non, pourquoi cette erreur est-elle affichée?
Oui , être au-delà de la portée de la résolution implicite semble probable, mais le message est confus. Tout fonctionne si vous spécifiez explicitement le paramètre type: 'test [Foo.type]' dans votre exemple. – Impredicative