Haskell 中的运算符与匿名函数优先级
Operator vs Anonymous function precedence in Haskell
在Haskell下面的表达式中:
a \b -> c $ d
是
• 无效
• (a (\b ->c)) d
• (a (\b -> (c d))
为什么?
它在 vanilla Haskell 中是无效的,因为 lambda 不能直接用作函数的参数而没有中间运算符。正确的版本需要使用$
或者括号:
a \b -> c $ d
a $ \b -> c $ d
a ( \b -> c $ d )
但是,没有根本原因不允许 lambda(或 case
、if
、do
或 let
表达式),因为这不是模棱两可的。 BlockArguments
扩展(在 GHC 8.6.1 中添加)允许这些语法结构直接作为函数的参数。启用后,它解析与上面相同,如:
(a (\b -> (c $ d))
不解析为*(a (\b -> c)) d
的原因是lambda的范围在Haskell Report §3中定义为向右延伸至可能(强调):
The grammar is ambiguous regarding the extent of lambda abstractions, let expressions, and conditionals. The ambiguity is resolved by the meta-rule that each of these constructs extends as far to the right as possible.
换句话说,可以认为 lambda 的主体比任何其他表达式具有 较低 的优先级。这个符号是直接从 lambda 演算中借用的,其中 a λb。 c d 等同于 (a (λb. (c d))).
请注意,我没有在此处删除 $
:这两个表达式是不同的,即使它们的计算结果相同:
f x
f $ x
第一个是函数f
对参数x
的应用;第二个是运算符 ($)
对参数 f
和 x
的应用。与所有中缀运算符一样,它是普通前缀函数调用的语法糖:
($) f x
($)
定义为 right-associative 运算符(即 x $ y $ z
= x $ (y $ z)
,not *(x $ y) $ z
) 具有最低的运算符优先级,在 Prelude
中声明 infixr 0
。您可以在 GHCi 中使用 :info
(或 :i
)命令查看有关操作员的信息:
> :info $
($) :: (a -> b) -> a -> b -- Defined in ‘GHC.Base’
infixr 0 $
在Haskell下面的表达式中:
a \b -> c $ d
是
• 无效
• (a (\b ->c)) d
• (a (\b -> (c d))
为什么?
它在 vanilla Haskell 中是无效的,因为 lambda 不能直接用作函数的参数而没有中间运算符。正确的版本需要使用$
或者括号:
a \b -> c $ d
a $ \b -> c $ d
a ( \b -> c $ d )
但是,没有根本原因不允许 lambda(或 case
、if
、do
或 let
表达式),因为这不是模棱两可的。 BlockArguments
扩展(在 GHC 8.6.1 中添加)允许这些语法结构直接作为函数的参数。启用后,它解析与上面相同,如:
(a (\b -> (c $ d))
不解析为*(a (\b -> c)) d
的原因是lambda的范围在Haskell Report §3中定义为向右延伸至可能(强调):
The grammar is ambiguous regarding the extent of lambda abstractions, let expressions, and conditionals. The ambiguity is resolved by the meta-rule that each of these constructs extends as far to the right as possible.
换句话说,可以认为 lambda 的主体比任何其他表达式具有 较低 的优先级。这个符号是直接从 lambda 演算中借用的,其中 a λb。 c d 等同于 (a (λb. (c d))).
请注意,我没有在此处删除 $
:这两个表达式是不同的,即使它们的计算结果相同:
f x
f $ x
第一个是函数f
对参数x
的应用;第二个是运算符 ($)
对参数 f
和 x
的应用。与所有中缀运算符一样,它是普通前缀函数调用的语法糖:
($) f x
($)
定义为 right-associative 运算符(即 x $ y $ z
= x $ (y $ z)
,not *(x $ y) $ z
) 具有最低的运算符优先级,在 Prelude
中声明 infixr 0
。您可以在 GHCi 中使用 :info
(或 :i
)命令查看有关操作员的信息:
> :info $
($) :: (a -> b) -> a -> b -- Defined in ‘GHC.Base’
infixr 0 $