Подтвердить что ты не робот

Haskell Приоритет: Лямбда и оператор

Я обнаружил, что приоритет и ассоциативность - это большое препятствие для меня, чтобы понять, что грамматика пытается выразить на первый взгляд кодом 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 → =).

Но нет информации для → , так как это не оператор.

Может кто-то из вас, ребята, дать некоторую ссылку, чтобы облегчить понимание этой грамматики?

4b9b3361

Ответ 1

Правило для лямбда довольно просто: тело лямбды простирается как можно дальше вправо, не ударяя несбалансированную скобку.

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

Ответ 2

Хорошее эмпирическое правило состоит в том, что вы никогда не сможете создать пользовательский оператор, который имеет приоритет над встроенными синтаксическими конструкциями. Например, рассмотрим этот пример:

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)