Почему Монастырь Хаскелла связывает лево-ассоциативный?
Операторы >>=
и >>
являются и 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; (...)}
. Как и раньше, обезжиривание >>
здесь, по-видимому, следует >>=
ради последовательности.