为什么不适用的隐式转换会引入歧义



本例(Scala 2.10.3)的设置:

trait S[A]
trait T[A]
implicit class X[A : S](a: A) { def foo() { } }
implicit class Y[A : T](a: A) { def foo() { } }
implicit object I extends S[String]

这编译:

new X("").foo()

这不是:

new Y("").foo()

因为不存在隐式CCD_ 1。

could not find implicit value for evidence parameter of type T[String]
new Y("").foo()
^

因此,我假设scalac可以明确地应用从StringX的隐式转换:

"".foo()

但我们得到的却是:

type mismatch;
found   : String("")
required: ?{def foo: ?}
Note that implicit conversions are not applicable because they are ambiguous:
both method X of type [A](a: A)(implicit evidence$1: S[A])X[A]
and method Y of type [A](a: A)(implicit evidence$1: T[A])Y[A]
are possible conversion functions from String("") to ?{def foo: ?}
"".foo()
^

这是故意的吗?scalac在枚举候选者时是否不应该考虑每个转换是否真的有效?

我的非学术观点是,隐式在设计上并不意味着每次看起来都应该起作用。我认为这是个好主意,否则你很容易陷入一个隐含的地狱。您可以通过添加更多的隐式转换层来扩展您的示例。仅仅通过查看代码很难判断实际调用了哪个函数。有定义明确的规则,但我只记得,如果从代码中看不出发生了什么,那就不起作用。

我想说,你的代码打破了一次一个规则,这导致打破了非歧义规则。A : S只是一种句法糖,可以重写为:

implicit class X[A](a: A)(implicit e: S[A]) { def foo() { } }
implicit class Y[A](a: A)(implicit e: T[A]) { def foo() { } }

如果没有"第二"隐式级别(方法参数e)的解析,则类XY在编译器看来是相同的,因此是不明确的。正如链接的文档所说:">为了理智起见,当编译器已经在尝试另一个隐式转换时,它不会插入进一步的隐式转换。">

最新更新