使用上下文绑定时找不到隐式值
Could not find implicit value while using 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)
但在更改之后编译开始失败并出现错误:
could not find implicit value for parameter 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]]
好的,我理解这个输出。但是为什么它在隐式参数的情况下起作用?
我没有这方面的参考,但根据我的经验,在之前任何其他"explicit"隐式参数搜索对应于上下文绑定的隐式;你的方法
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]
并且由于歧义,此时 fails ;此时它停止搜索其他任何东西。令人困惑的是 错误消息 ,恕我直言,它应该类似于 "failed searching for Acceptable[T]: ambiguous implicits" 或类似的东西。
为什么其他方法有效?因为隐式参数的 order。编译器将首先搜索 f: I => T
,这很可能会将 T
绑定到 Int
、,然后 我们确实有一个唯一的 Acceptable[Int]
隐含在范围内。一般
- 我不会混用上下文边界和隐式参数
- 隐式参数的顺序很重要,应该这样排列,找到一个唯一确定下一个
据我所知,所有这些都没有规定,取决于当前的实施;以上内容主要基于我调试隐式错误的经验。
我正在使用以下用 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)
但在更改之后编译开始失败并出现错误:
could not find implicit value for parameter 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]]
好的,我理解这个输出。但是为什么它在隐式参数的情况下起作用?
我没有这方面的参考,但根据我的经验,在之前任何其他"explicit"隐式参数搜索对应于上下文绑定的隐式;你的方法
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]
并且由于歧义,此时 fails ;此时它停止搜索其他任何东西。令人困惑的是 错误消息 ,恕我直言,它应该类似于 "failed searching for Acceptable[T]: ambiguous implicits" 或类似的东西。
为什么其他方法有效?因为隐式参数的 order。编译器将首先搜索 f: I => T
,这很可能会将 T
绑定到 Int
、,然后 我们确实有一个唯一的 Acceptable[Int]
隐含在范围内。一般
- 我不会混用上下文边界和隐式参数
- 隐式参数的顺序很重要,应该这样排列,找到一个唯一确定下一个
据我所知,所有这些都没有规定,取决于当前的实施;以上内容主要基于我调试隐式错误的经验。