为什么 ((_: Int, _: Int) => _ / _) 在 ((_: Int) / (_: Int)) 编译时不编译?

Why does ((_: Int, _: Int) => _ / _) not compile when ((_: Int) / (_: Int)) does?

我正在学习 Scala,有一个非常基本的问题。考虑以下两个使用占位符语法的表达式 -

// Syntax A  
val fnA = (_: Int, _: Int) => _ / _

// Syntax B
val fnB = (_: Int) / (_: Int) 

及其尝试的应用程序 -

// Syntax A
fnA(33, 3)

// Syntax B
fnB(33, 3)

在这两个中,只有 B 和 App(B) 是有效语法,我不确定为什么。如果编译器能够推断出 fnB 中的参数(以及应用它们的顺序),为什么它不能为 fnA 做到这一点?我提出问题的前提是 fnBfnA 的 shorthand,而且我很确定这种推理存在缺陷。我只是不确定这个缺陷是什么。

箭头左边下划线的含义=>

(_: Int, _: Int) => ...

与中缀运算符周围的下划线的含义不同 /

(_: Int) / (_: Int) 

前者的意思是

"We are defining a function that takes two arguments, however we will not use these arguments in the body of the function"

而后者是 shorthand 用于定义两个参数的函数

(x: Int, y: Int) => x / y

例如,

(_: Int, _: Int) => (_: Int) / (_: Int)

脱糖成

(a: Int, b: Int) => ((x: Int, y: Int) => x / y)

我们看到参数 ab 没有在正文中使用,而正文恰好是另一个函数 ((x: Int, y: Int) => x / y).

Daniel将这两个意思记录为

_ + _             // Anonymous function placeholder parameter
_ => 5            // Discarded parameter

作为旁注,考虑类型级别的一些类似情况,涉及类型构造函数及其边界,其中下划线的含义取决于上下文

CC[_] <: Iterable[_]  

就我个人而言,我的头脑欺骗我认为它等同于

CC[x] <: Iterable[x]  

然而事实并非如此,<:左边的下划线与右边

的意思不同
CC[x] <: Iterable[y] forSome {type y}

请注意 x 没有出现在 Iterable[y] forSome {type y} 中。 Adrian 在 Common Pitfalls:

下记录了这一点

...perhaps surprisingly, CC[_] <: Traversable[_] is not equivalent to CC[X] <: Traversable[X]. The former expands to CC[X] <: Traversable[T] forSome {type T}, where T is existentially bound and thus unrelated to X.

并在 comment to type bounds on type constructor

comparing the level of types and values, it is quite unfortunate that the type-level underscore behaves differently from the value-level underscore. At the value level, _ + _ indeed stands for (x, y) => x + y, a function. As hinted at in my other comment, the type-level underscore is context-sensitive, and it never introduces a type-level function. It's either an anonymous type parameter definition or an anonymous existential. Neither of these have value-level equivalents.

因此,我们应该小心地在其上下文中解释下划线的含义。