scala - 使用上下文绑定(bind)时找不到隐式值

标签 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)

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

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]]

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

最佳答案

我没有这方面的引用,但根据我的经验,在任何其他“显式”隐式参数之前搜索与上下文绑定(bind)相对应的隐式;你的方法

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)

您可以轻松检查它也不起作用。为什么?从输出看,编译器首先尝试查找隐式 Acceptable[T]由于模棱两可,它在这一点上失败了;此时它停止搜索其他任何内容。令人困惑的是错误消息,恕我直言,它应该类似于“搜索Acceptable[T] 失败:模糊隐含”或类似的东西。

为什么其他方法有效?因为隐式参数的顺序。编译器将首先搜索 f: I => T这很可能会绑定(bind)TInt ,然后我们确实有一个唯一的 Acceptable[Int]隐含在范围内。一般来说
  • 我不会混合上下文边界和隐式参数
  • 隐式参数的顺序很重要,应该安排它们以便找到一个唯一地确定下一个

  • 据我所知,所有这些都没有指定,取决于当前的实现;以上主要基于我调试隐含错误的经验。

    关于scala - 使用上下文绑定(bind)时找不到隐式值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40833931/

    相关文章:

    mysql - 如何生成行号作为现有表的列?

    scala - 使用 Scala 闭包,捕获的变量何时开始存在于 JVM 堆上?

    scala - 加特林。连接异常 : connection timed out:

    scala - 防止 Scala 特征成为 SAM 类型

    scala - 如何对 2 个以上的情况确定隐式优先级

    Scala:如何在这里进行上下文绑定(bind)的 List[T] 转换?

    mysql - 如何让Slick建表语句使用InnoDB

    scala - 为什么对于任何给定的类型参数,类型类只能有一种实现?

    scala - 案例类和同伴的不同顺序的隐式解析

    scala - 如何避免具有多个类型类关系的模棱两可的转换链?