Haskell Precedence: Lambda and operator

2019-03-18 03:44发布

I found precedence and associativity is a big obstacle for me to understand what the grammar is trying to express at first glance to haskell code.

For example,

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

By experiment, I finally got it means,

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

instead of

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

Which works as:

*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)]

I can get info from ghci for (>>=) as an operator, (infixl 1 >>=).

But there's no information for -> since it's not an operator.

Could someone of you guys give some reference to make this grammar thing easier to grasp?

2条回答
三岁会撩人
2楼-- · 2019-03-18 04:12

The rule for lambdas is pretty simple: the body of the lambda extends as far to the right as possible without hitting an unbalanced parenthesis.

f (\x -> foo (bar baz) *** quux >>= quuxbar)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                       body
查看更多
成全新的幸福
3楼-- · 2019-03-18 04:18

A good rule of thumb seems to be that you can never make a custom operator that has precedence over built in syntactic constructs. For instance consider this example:

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

Regardless of the associativity of ***, no one would expect it to binds as:

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

There aren't a lot of syntactic constructs in Haskell (do and case are a little special because of layout syntax) but let can be used as another example:

(let x = y in y *** x) /= ((let x = y in y) *** x) 
查看更多
登录 后发表回答