使用Context Bound时无法找到隐含值

时间:2016-11-27 21:10:12

标签: 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]]

成功编译。

正如您所见,a: Acceptable[T]参数应该很容易转换为context bound

implicit def test[I, T: Acceptable](implicit f: I => T): Enc[I] =
    Enc[I](f)

但是在那之后,改变编译开始失败并出现错误:

  

找不到参数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]]

好的,我理解这个输出。但是为什么它在隐式参数的情况下有用呢?

1 个答案:

答案 0 :(得分:7)

我没有对此的引用,但根据我的经验,在任何其他“显式”隐式参数之前搜索对应于上下文绑定的implicits;你的方法

implicit def test[I, T: Acceptable](implicit f: I => T): Enc[I] =
  Enc[I](f)

相当于

implicit def test2[I, T](implicit a: Acceptable[T], f: I => T): Enc[I] =
  Enc[I](f)

您可以轻松检查哪个也不起作用。为什么?由于模糊性,从输出看起来编译器 first 试图寻找隐式Acceptable[T]并且在此时失败;此时它停止搜索其他任何东西。令人困惑的是错误消息,恕我直言应该是“搜索可接受的[T]:含糊不清的”或类似的内容。

为什么其他方法有效?因为隐含参数的顺序。编译器将首先搜索f: I => T,这很可能会将T绑定到Int然后我们会隐含一个唯一的Acceptable[Int]范围。一般来说

  • 我不会混合上下文边界和隐式参数
  • 隐式参数的顺序很重要,应该对它们进行排列,以便找到一个确定下一个唯一的

据我所知,所有这些都没有规定,取决于目前的实施情况;以上主要是根据我的经验调试暗示错误。