2012-06-28 73 views
17

我发现优先级和关联性对我来说是一个很大的障碍,让我能够理解语法在第一眼看到haskell代码时想表达什么。Haskell优先级:Lambda和运算符

例如,

blockyPlain :: Monad m => m t -> m t1 -> m (t, t1) 
blockyPlain xs ys = xs >>= \x -> ys >>= \y -> return (x, y) 

通过实验,我终于得到了它的意思,

blockyPlain xs ys = xs >>= (\x -> (ys >>= (\y -> return (x, y)))) 

,而不是

blockyPlain xs ys = xs >>= (\x -> ys) >>= (\y -> return (x, y)) 

其中的工作原理:

*Main> blockyPlain [1,2,3] [4,5,6] 
[(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)] 

我可以从ghci获取(>> =)作为操作符的信息,(infixl 1 >> =)。

但是没有关于 - >的信息,因为它不是运营商。

有人可以给你一些参考,使这个语法的东西更容易掌握?

+0

的[Haskell的报告](http://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-220003)是Haskell语法的权威性参考,虽然也许BNF语法对于您的问题有点低级别问...? –

回答

23

lambda的规则非常简单:lambda的主体尽可能向右延伸而不会碰到不平衡的括号。

f (\x -> foo (bar baz) *** quux >>= quuxbar) 
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
         body 
+3

这意味着它适用于最后。也就是说,( - >)的优先级低于其他任何运算符。我相信'do'和(< - )也是如此,它们尽可能地向右延伸,最后应用,并且优先于任何运算符。 –

+4

我真的不喜欢优先考虑的术语“第一”和“最后” - 我认为它与评估顺序的分组相混淆。这是我在数学教学中遇到的问题。我喜欢“紧张”和“松散”,认为运营商坚持他们的操作数。无论如何,' - >'并不是真正的中缀运算符,因为它不会连接两个项;相反,lambda是一个表达式的语法形式。这就是为什么我没有回答运营商的问题。 – luqui

+1

这两点都很好。 “第一”和“最后”是在讨论操作顺序时,在大多数k-12(而不是少数本科)数学课程中使用的短语。我的尝试是将那些常用(虽然不太准确)的术语应用于您的非常好的答案。 –

7

一个很好的经验法则似乎是,你永远不能做一个自定义运算符,它优先于内置的语法结构。例如考虑这个例子:

if b then f *** x else f *** y 

不管***关联性的,没有人会指望它结合为:

(if b then f *** x else f) *** y 

有没有很多在Haskell语法结构的(docase是因为布局语法的一点特殊),但let可以用作另一示例:

(let x = y in y *** x) /= ((let x = y in y) *** x) 
+2

除功能应用程序和记录更新... – luqui