在尝试回答这个问题时,我想出了以下代码:
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()
}
请注意,这IntLike
只是为了让我相信这不是关注的问题Int
。
这似乎是一个相当标准的隐式使用,如果不好的话,我期待它能够愉快地工作。但是,在调用purchaseCandles()
REPL 时会产生以下错误:
错误:不明确的隐式值:类型 => scala.collection.generic.CanBuildFrom[String,Char,String] 的对象 Predef 中的值 StringCanBuildFrom 和 Tree 类型的值 guest 都匹配预期的类型 A
我一辈子都看不到这是怎么回事。A 必然有一个 的视图边界IntLike
,这是我刚刚发明的一种类型。REPL 确认没有可用的隐式视图:
scala> 隐式[Tree => IntLike]
res14: 树 => IntLike = function1
但
scala> 隐式[scala.collection.generic.CanBuildFrom[String, Char, String] => IntLike]
:18: 错误:scala.collection.generic.CanBuildFrom[String,Char,String] => IntLike 没有可用的隐式视图。
那么怎么可能StringCanBuildFrom
是合适的类型呢?编译器是否能够解析多个依赖隐式,如果不能,为什么会显示这个错误?