我发现优先级和关联性对我来说是一个很大的障碍,让我理解语法乍看之下对haskell代码的表达。
例如,
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 :(得分:24)
lambdas的规则非常简单:lambda的主体尽可能向右延伸而不会碰到不平衡的括号。
f (\x -> foo (bar baz) *** quux >>= quuxbar)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
body
答案 1 :(得分:7)
一个好的经验法则似乎是你永远不能创建一个优先于内置语法结构的自定义运算符。例如,考虑这个例子:
if b then f *** x else f *** y
无论***
的相关性如何,没有人会认为它会绑定为:
(if b then f *** x else f) *** y
Haskell中没有很多语法结构(do
和case
因布局语法而有点特殊)但let
可以用作另一个例子:
(let x = y in y *** x) /= ((let x = y in y) *** x)