简体   繁体   中英

Haskell Precedence: Lambda and operator

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?

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

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) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM