【问题标题】:Implicit not resolved on high order function隐式未解决高阶函数
【发布时间】:2014-09-23 15:23:57
【问题描述】:

我有一个函数create将提供op: DSLContext => T的参数DSLContext:

def create[T](op: DSLContext => T)(implicit errorHandler: Throwable => Unit):Option[T] = {
  ...
  op(new DSLContext)
  ...
}

然后我将以下函数传递给create

def query(implicit dsl:DSLContext)

这是电话

create(query)

我得到了这个编译器错误:

找不到参数 dsl 的隐式值:org.jooq.DSLContext [错误] 创建(查询)

我可以这样解决这个问题:create {implicit dsl => query}

但是我想知道为什么编译器无法将隐式参数 dsl 解析为给定参数?

【问题讨论】:

  • 你需要DSLContext => T,你通过DSLContext并得到一个错误。当你通过DSLContext => T 时,没有错误。怎么了?
  • 相同。不太确定你在期待什么。
  • @JeanLogeart 查询是 DSLContext => T,而不仅仅是 DSLContext。因此,当我将查询作为 create 的参数传递时,我传递了一个采用 DSLContext 并返回 T 的函数。
  • 他想将方法引用而不是匿名函数传递给createquery 就是那个方法。换句话说,他想部分应用带有隐式参数的方法,这就是编译器感到困惑的地方。
  • @Hexx 我建议您修改query 以采用普通(非隐式)参数,并将其分配给本地implicit valdef query(dsl: DSLContext) = { implicit val idsl = dsl; ... }.

标签: scala implicit


【解决方案1】:

这里的问题是,当您传递一个预期为函数的方法时,编译器需要执行 eta 扩展来转换它。

换句话说,方法query需要变成Function1[DSLContext, T]

但是,编译器需要解析隐式参数才能应用 eta 扩展。在您的情况下,范围内没有 DSLContext,因此编译器无法这样做。

您可以通过一个更简单的示例重现此行为,这是一个演示它的 REPL 会话:

scala> def foo(implicit i: Int) = "hello"
foo: (implicit i: Int)String

scala> foo _
<console>:10: error: could not find implicit value for parameter i: Int
              foo _
              ^

scala> implicit val x = 5
x: Int = 5

scala> foo _
res3: scala.collection.immutable.WrappedString = hello

_ 手动触发 eta 扩展。

作为记录,这在language reference,第 6.26.2 段中有所描述。

如果方法只接受隐式参数,则隐式参数按照 §7.2 的规则传递。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-24
    • 2013-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多