【问题标题】:Operator vs Anonymous function precedence in HaskellHaskell中的运算符与匿名函数优先级
【发布时间】:2020-09-02 02:47:36
【问题描述】:

在 Haskell 中如下表达式:

 a \b -> c $ d

要么是

• 无效

(a (\b ->c)) d

(a (\b -> (c d))

为什么?

【问题讨论】:

    标签: haskell lambda syntax anonymous-function operator-precedence


    【解决方案1】:

    它在 vanilla Haskell 中是无效的,因为 lambda 不能直接用作没有中间运算符的函数的参数。正确的版本需要使用$或者括号:

    a   \b -> c $ d
    a $ \b -> c $ d
    a ( \b -> c $ d )
    

    但是,没有根本原因不允许 lambda(或 caseifdolet 表达式)在那里,因为它不是模棱两可的。 BlockArguments 扩展(在GHC 8.6.1 中添加)允许这些句法结构直接作为函数的参数。启用该功能后,它的解析方式与上面相同,如下所示:

    (a (\b -> (c $ d))
    

    解析为 *(a (\b -> c)) d 的原因是 lambda 的范围在 Haskell Report §3 中定义为尽可能向右延伸(添加了重点):

    关于lambda 抽象、let 表达式和条件句的范围,语法是模棱两可的。通过这些结构中的每一个都尽可能向右延伸的元规则来解决歧义。

    换句话说,可以认为 lambda 的主体具有比任何其他表达式更低的优先级。这个符号直接从 lambda 演算中借用,其中 a λbc d 等同于 (ab. (c d)))。

    请注意,我没有在这里删除$:这两个表达式是不同的,即使它们的计算结果相同:

    f x
    f $ x
    

    第一个是函数f对参数x的应用;第二个是将运算符($) 应用于参数fx。像所有中缀运算符一样,它是普通前缀函数调用的语法糖:

    ($) 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 $
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-07
      相关资源
      最近更新 更多