将函数隐式参数传递给高阶函数后,函数隐式参数不再如此

Function implicit parameters not any more so after passing it to a higher order function

在 Scala 中,您可以执行以下操作:

def foo(implicit v: Int) = println(v);
def h(x: Int) = { implicit val i: Int = x; foo }

h(42)
> 42

h 调用获取 foo 引用作为闭包。

尝试将 foo 作为参数传递给 h 并不奇怪:

def g(x: Int)(f: Int => Unit) = { implicit val i: Int = x; f }

但这行不通:

g(1)(foo)
> error: could not find implicit value for parameter v: Int

我认为正在发生的事情是 foo 被调用作为实际参数的评估。 对吗?

当传递一个带有普通参数列表(非隐式)的函数时,该函数未被计算:

def foo2(v: Int) = println("Foo2")
g(1)(foo2)
> Int => Unit = <function1>

这是预期结果,foo2 评估未尝试作为实际参数的评估。

为什么在没有隐式值可用时将 foo 计算为实际参数?

赋值也是如此:

val fooref: Int => Unit = foo
> error: could not find implicit value for parameter v: Int

这就像因为 Int => UnitInt 参数被标记为隐式的函数不匹配,编译器将其丢弃为有效的实际参数并因此尝试对其求值。未找到声明的隐式值来完成调用。

如果是这样,用隐式参数表达函数类型的方式应该是什么?

不幸的是,函数不能有隐式参数——只有方法可以。

在表达式g(1)(foo)中,foo方法转换为函数(也称为作为 eta 展开)。 Scala 规范的 section 6.26.2 声明隐式参数在 之前 eta 扩展应用。

看到这张票:implicit methods behave suboptimally when used non-implicitly

函数 gf 参数的类型是 Function1[Int, Unit]Function1[A, B] 是单一方法 apply(a: A): B 的特征,其中 a 不是隐式的。因此,您不能从 foo 创建 Function1[Int, Unit] 的实例 - 它没有正确的签名。