请解释Haskell如何确定优先级的部分,带有多个参数的函数和多个部分应用的函数。有时我发现当整个表达式采用多个参数时,很难弄清楚哪个部分函数会应用哪个参数。
以下是一些示例函数,但我确信不同的示例可能更具说明性。第一部分取自“有效的应用程序设计”一文。
sequence :: [IO a] → IO [a]
sequence [] = return []
sequence (c : cs) = return (:) `ap` c `ap` sequence cs
(.) (.)
(.) (.) (.)
是否有工具将此类表达式转换为lambda表达式?
答案 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`
默认情况下,具有左关联性,优先级低于函数应用程序,但可以使用infixl
或infixr
声明对其进行修改。 ap
函数尚未从默认值修改,因此sequence
的rhs为:
((return (:)) `ap` c) `ap` (sequence cs)
或等效
ap (ap (return (:)) c) (sequence cs)