了解Haskell优先级规则如何与多个部分应用程序一起使用

时间:2013-06-21 19:38:17

标签: haskell

请解释Haskell如何确定优先级的部分,带有多个参数的函数和多个部分应用的函数。有时我发现当整个表达式采用多个参数时,很难弄清楚哪个部分函数会应用哪个参数。

以下是一些示例函数,但我确信不同的示例可能更具说明性。第一部分取自“有效的应用程序设计”一文。

sequence :: [IO a] → IO [a]
sequence [] = return []
sequence (c : cs) = return (:) `ap` c `ap` sequence cs

(.) (.)
(.) (.) (.)

是否有工具将此类表达式转换为lambda表达式?

2 个答案:

答案 0 :(得分:8)

带有 no 参数的括号中的运算符被视为普通标识符。因此(+)add的行为方式完全相同。这意味着它以前缀形式使用,并且不会出现优先级问题。

考虑到这一点,我们可以想象写下以下内容:

compose = (.)
compose compose compose

后一版本与使用(.)的混淆版本相同。它有助于记住函数应用程序是正确的关联,因此表达式与:

相同
(compose compose) compose

就优先级而言,带有参数的运算符部分(如(+ 1)(1 +))的行为与普通标识符的行为相同。因此,如果您定义next = (+ 1),则两者的行为都相同。

就无点代码而言,pointful包有一个命令行工具,它采用无点函数并尝试将其转换为一堆lambdas。您还可以使用@unpl。

在#haskell IRC频道上从lambdabot获取此功能

你可以用cabal安装一下并调用它:

cabal install pointful
pointful

答案 1 :(得分:3)

a b c d等函数应用程序中的标识符列表被解析为(((a b) c) d)。带括号的中缀运算符(.)被视为标识符。

因此(.) (.) (.)解析为((.) (.)) (.)

一般来说,像这样的变量运算符

`functionname`
默认情况下,

具有左关联性,优先级低于函数应用程序,但可以使用infixlinfixr声明对其进行修改。 ap函数尚未从默认值修改,因此sequence的rhs为:

((return (:)) `ap` c) `ap` (sequence cs)

或等效

ap (ap (return (:)) c) (sequence cs)