将函数隐式参数传递给高阶函数后不再是隐式参数

8

在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 => Unit 不匹配一个将 Int 参数标记为 implicit 的函数, 编译器会将其丢弃作为有效的实际参数,因此试图评估它。没有找到一个声明的 implicit 值来满足调用。

如果是这种情况,有什么方法可以表达具有隐式参数的函数类型?

2个回答

12

很遗憾,函数不能有隐式参数 - 只有方法可以。

在表达式g(1)(foo)中,foo方法转换为函数(也称为eta扩展)。并且Scala规范的第6.26.2节指出,隐式参数应用于eta扩展之前。

参见此票:非隐式使用隐式方法时效果不佳


1
函数g的参数f的类型是Function1[Int, Unit]Function1[A, B] 是一个带有单个方法apply(a: A): B的特质,其中a不是隐式的。因此,您无法从foo创建Function1[Int, Unit]的实例 - 它不会具有正确的签名。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接