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

时间:2015-09-22 12:20:03

标签: scala function implicit implicits

在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参数被标记为隐式的函数不匹配,编译器会将其作为有效的实际参数丢弃,因此会尝试对其进行评估。找不到声明的隐含值来完成调用。

如果是这种情况,用隐式参数表达函数类型的方式是什么?

2 个答案:

答案 0 :(得分:11)

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

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

查看此票证:implicit methods behave suboptimally when used non-implicitly

答案 1 :(得分:1)

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