Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell Precedence: Lambda and operator

Tags:

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?

like image 935
ning Avatar asked Jun 28 '12 01:06

ning


2 Answers

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
like image 62
luqui Avatar answered Nov 11 '22 13:11

luqui


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) 
like image 29
Jonas Duregård Avatar answered Nov 11 '22 13:11

Jonas Duregård