
On Wed, Jun 25, 2014 at 3:14 PM, Richard Eisenberg
On Jun 25, 2014, at 12:52 AM, John Lato
wrote: The compiler makes assumptions about associativity when de-sugaring do-notation. If the monad laws aren't followed, it's possible for these two blocks to show different behavior (given that a,b,c are all values of the misbehaved Monad instance):
do { a; b; c }
a >> b >> c
I think everyone can agree that this is surprising, at the very least. Although it's not the compiler that's generating bad code here.
As far as I know, GHC makes no assumptions about associativity, or any class-based laws. The effect John observes above is accurate, but it is a direct consequence of the design of Haskell in the Haskell 2010 Report, not any assumptions in the compiler.
Specifically, Section 3.14 ( https://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-470003.1...) says that `do { e; stmts }` desugars to `e >> do {stmts}`. In the case of `do { a; b; c }`, that means we get `a >> (b >> c)`. However, in Table 4.1 in Section 4.4.2 (under https://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-800004....), we see that (>>) is *left*-associative, meaning that `a >> b >> c` means `(a >> b) >> c`.
Are the different meanings here an "assumption" of associativity? I suppose one could construe it that way, but I just see `do { a; b; c}` and `a >> b >> c` as different chunks of code with different meanings. If the monad in question upholds the associativity law, then the chunks evaluate to the same result, but they're still distinct.
Great explanation! Would you say that the main reason for implementing monads so >> is associative is to make sure the do notation does the "right thing"? Monad is a notion from math which was imported into Haskell. As far as I know, the reason behind it was to give Haskell the possibility of doing IO while keeping itself pure. If there was a data type just like Moand, with
=, >>, return and all. It behaved exactly the same, but no one cared about identity or associativity, then it wouldn't be a monad, but it would solve the computation with side-effects thing just the same. Why was associativity and identity brought to the language as well? What is there to be gained by such a law which can't be enforced by the compiler?