如何解决Haskell中的运算符vs匿名函数优先级
在Haskell中,以下表达式:
a \b -> c $ d
是
•无效
•(a (\b ->c)) d
•(a (\b -> (c d))
为什么?
解决方法
在香草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
的原因是,在Haskell Report §3中将lambda的范围定义为尽可能向右扩展(添加了强调) :
关于 lambda抽象程度,let表达式和条件的语法是模棱两可的。元规则解决了这种歧义,即这些结构中的每一个都尽可能向右延伸。
换句话说,lambda的主体可以被认为比任何其他表达式具有 lower 更低的优先级。这种表示法是直接从lambda演算中借用的,其中 a λ b 。 c d 与( a (λ b 。( c d )))。
请注意,我并没有在此处删除$
:这两个表达式的计算结果相同,尽管它们是不同的:
f x
f $ x
第一个是函数f
在自变量x
上的应用;第二个是运算符($)
在参数f
和x
上的应用。像所有中缀运算符一样,它是常规前缀函数调用的语法糖:
($) f x
($)
被定义为具有最低优先级的右关联运算符(即x $ y $ z
= x $ (y $ z)
, not * (x $ y) $ z
) ,在infixr 0
中带有声明Prelude
。您可以使用GHCi中的:info
(或:i
)命令查看有关运算符的信息:
> :info $
($) :: (a -> b) -> a -> b -- Defined in ‘GHC.Base’
infixr 0 $
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。