Почему Монастырь Хаскелла связывает лево-ассоциативный?

Операторы >>= и >> являются и infixl 1. Почему левая ассоциативность?

В частности, я наблюдаю эквивалентности:

(do a; b; c ) == (a >> (b >> c))   -- Do desugaring
(a >> b >> c) == ((a >> b) >> c)   -- Fixity definition

Таким do это делается по-разному, как естественно работает определение фиксации, что удивительно.

Ответ 1

>>= обязательно должно быть лево-ассоциативным.

Prelude> ["bla","bli di","blub"] >>= words >>= reverse
"albilbidbulb"
Prelude> ["bla","bli di","blub"] >>= (words >>= reverse)

<interactive>:3:30: error:
    • Couldn't match expected type ‘[[b0]]
                  with actual type ‘String -> [String]
    • Probable cause: ‘words is applied to too few arguments
      In the first argument of ‘(>>=), namely ‘words
      In the second argument of ‘(>>=), namely ‘(words >>= reverse)
      In the expression:
        ["bla", "bli di", "blub"] >>= (words >>= reverse)

И >> значительной степени следует >>=; если бы у него была другая фиксация, это не только показалось бы странным, как сказал Леннарт, это также помешало бы вам использовать оба оператора в цепочке:

Prelude> ["bla","bli di","blub"] >>= words >> "Ha"
"HaHaHaHa"
Prelude> infixr 1 ⬿≫; (⬿≫) = (>>)
Prelude> ["bla","bli di","blub"] >>= words ⬿≫ "Ha"

<interactive>:6:1: error:
    Precedence parsing error
        cannot mix ‘>>= [infixl 1] and ‘⬿≫ [infixr 1] in the same infix expression

Ответ 2

>>= лево-ассоциативный, потому что он удобен. Мы хотим, чтобы m >>= f1 >>= f2 анализировалось как (m >>= f1) >>= f2, а не как m >>= (f1 >>= f2), что, скорее всего, не будет вводить проверку, как указано в комментариях.

Ассоциативность >> однако, является просто зеркалом >>=. Скорее всего, это необходимо для согласованности, поскольку мы можем доказать, что >> ассоциативно через третий закон монады: (m >>= f) >>= g ≡ m >>= ( \x → fx >>= g ). То есть, его ассоциативность теоретически не имеет значения. Вот доказательство:

-- Definition:
a >> b ≡ a >>= (\_ -> b)

-- Proof: (a >> b) >> c ≡ a >> (b >> c)
  (a >> b) >> c
≡ (a >>= (\_ -> b)) >> c                  -- [Definition]
≡ (a >>= (\_ -> b)) >>= (\_ -> c)         -- [Definition]
≡ a >>= (\x -> (\_ -> b) x >>= (\_ -> c)) -- [Monad law]
≡ a >>= (\_ -> b >>= (\_ -> c))           -- [Beta-reduction]
≡ a >>= (\_ -> b >> c)                    -- [Definition]
≡ a >> (b >> c)                           -- [Definition]
∎

do -notation де-сахара по-разному, потому что у него другая цель. По сути, поскольку -notation по существу выписывает лямбду, необходима правая ассоциация. Это связано с тем, что m >>= (\v → (...)) записывается так do {v <- m; (...)} как do {v <- m; (...)} do {v <- m; (...)}. Как и раньше, обезжиривание >> здесь, по-видимому, следует >>= ради последовательности.