Trying to answer this question , I came up with the following code:
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() }
Note that IntLike exists only to convince me that this is not an Int focused issue.
This seems pretty standard, if bad, using implicits, and I expected it to work happily. However, when calling purchaseCandles() REPL gives the following error:
error: ambiguous implicit values: both StringCanBuildFrom values ββin the Predef object of type => scala.collection.generic.CanBuildFrom [String, Char, String] and the guest value of the Tree type corresponds to the expected type A
For life, I cannot see how this happens. A must have an IntLike view IntLike , the type I just came up with. REPL confirms that there is no hidden view:
scala> implicitly [Tree => IntLike]
res14: Tree => IntLike = function1
but
scala> implicitly [scala.collection.generic.CanBuildFrom [String, Char, String] => IntLike]
: 18: error: implicit view is available from scala.collection.generic.CanBuildFrom [String, Char, String] => IntLike.
So, how StringCanBuildFrom be of the appropriate type? Is the compiler capable of resolving multiple dependent implications, and if not, why is this error displayed?