mix*_*xel 5 scala implicit context-bound
我正在使用以下用Scala 2.11.8编写的代码:
sealed trait Acceptable[T]
object Acceptable {
implicit object Int extends Acceptable[Int]
implicit object String extends Acceptable[String]
}
case class Enc[T](f: T => Any)
implicit def test[I, T](implicit f: I => T, a: Acceptable[T]): Enc[I] =
Enc[I](f)
val e = implicitly[Enc[Int]]
Run Code Online (Sandbox Code Playgroud)
它成功编译.
如您所见,a: Acceptable[T]参数应该很容易转换为上下文绑定:
implicit def test[I, T: Acceptable](implicit f: I => T): Enc[I] =
Enc[I](f)
Run Code Online (Sandbox Code Playgroud)
但在那之后,更改编译开始失败并出现错误:
找不到参数e的隐含值:app.Enc [Int]
为什么会这样?
更新:
我试过-Xlog-implicits编译选项和编译日志给我:
[info] /path/to/ScalaTest/src/main/scala/app/Main.scala:60: test is not a valid implicit value for app.Enc[Int] because:
[info] hasMatchingSymbol reported error: ambiguous implicit values:
[info] both object Int in object Acceptable of type app.Acceptable.Int.type
[info] and object String in object Acceptable of type app.Acceptable.String.type
[info] match expected type app.Acceptable[T]
[info] val e = implicitly[Enc[Int]]
[info] ^
[info] /path/to/ScalaTest/src/main/scala/app/Main.scala:60: app.test is not a valid implicit value for app.Enc[Int] because:
[info] hasMatchingSymbol reported error: ambiguous implicit values:
[info] both object Int in object Acceptable of type app.Acceptable.Int.type
[info] and object String in object Acceptable of type app.Acceptable.String.type
[info] match expected type app.Acceptable[T]
[info] val e = implicitly[Enc[Int]]
[info] ^
[error] /path/to/ScalaTest/src/main/scala/app/Main.scala:60: could not find implicit value for parameter e: app.Enc[Int]
[error] val e = implicitly[Enc[Int]]
Run Code Online (Sandbox Code Playgroud)
好的,我理解这个输出.但是为什么它在隐式参数的情况下有效呢?
我没有这方面的参考,但根据我的经验,在任何其他"显式"隐式参数之前搜索对应于上下文边界的implicits; 你的方法
implicit def test[I, T: Acceptable](implicit f: I => T): Enc[I] =
Enc[I](f)
Run Code Online (Sandbox Code Playgroud)
相当于
implicit def test2[I, T](implicit a: Acceptable[T], f: I => T): Enc[I] =
Enc[I](f)
Run Code Online (Sandbox Code Playgroud)
您可以轻松检查哪些也不起作用.为什么?从输出看起来,编译器首先试图寻找一个隐含的,Acceptable[T]并且由于模糊性,此时它失败了; 此时它停止搜索其他任何东西.令人困惑的是错误信息,恕我直言应该是"搜索可接受的[T]:模糊的含义"或类似的东西.
为什么其他方法有效?因为隐含参数的顺序.编译器将首先搜索f: I => T,这很可能会绑定T到Int,然后我们有一个独特的Acceptable[Int]范围内隐.一般来说
据我所知,这一切都没有规定,取决于目前的实施情况; 以上主要是根据我的经验调试暗示错误.