5

On the one hand the monadic bind operator >>= is left associative (AFAIK). On the other hand the monad law demands associativity, i.e. evaluation order doesn't matter (like with monoids). Besides, monads encode a value dependency by making the next effect depend on the result of the previous one, i.e. monads effectively determine an evaluation order. This sounds contradictory to me, which clearly implies that my mental representation of the involved concepts is wrong. How does it all fit together?

Will Ness
  • 70,110
  • 9
  • 98
  • 181
  • 2
    No time for a full answer (and I doubt I could give a better one than many others), but in brief the "associative law" for monads isn't associativity of the `>>=` operator itself - if you check the standard statement of the law you will see it's somewhat more involved. It's equivalent in fact to the associativity (in the normal sense) of the Kleisli composition operator. – Robin Zigmond Sep 07 '20 at 12:23
  • It *sounds* contradictory. Can you come up with a concrete example of why you think it is contradictory? – user253751 Sep 07 '20 at 12:25
  • 3
    "evaluation order doesn't matter" that's commutativity, not associativity. monads' associativity just means that it's OK for the `do` notation to be multi-line (it doesn't have to be binary, like `>>=`), to be re-grouped at will as long as the lines' order stays the same (so the inner brackets can be omitted). Just like the function composition's associativity means we can write composition chains non-parenthesized too. – Will Ness Sep 07 '20 at 20:49
  • @WillNess My understanding of the associative property is that it allows a composition of more than two semigroups, for instance, to be computed in parallel, because the order in which `op1 <> op2` operations are evaluated doesn't matter. I don't mean the order of operands but the `operand1 operator operand2` operations as a whole. However, this doesn't work for `>>=` anyway, because of the underlying type. –  Sep 07 '20 at 21:21
  • 2
    ah, now it's clear. so, with monads, as was already said here, what's associative is `>=>`. and its combinations *too* could be calculated in parallel, out of order! ***but,*** what it calculates is the combined action that is *yet to be run*. see? ***when*** the combined action runs, it'll run its constituent actions left-to-right, strictly in order. because that's how the underlying `>>=` is defined. (you really should've included that example of your understanding in the question from the start!) – Will Ness Sep 07 '20 at 21:30
  • @WillNess Ya, sorry, higher order confusion.. –  Sep 07 '20 at 21:34

1 Answers1

7

On the one hand the monadic bind operator >>= is left associative

Yes.

Prelude> :i >>=
class Applicative m => Monad (m :: * -> *) where
  (>>=) :: m a -> (a -> m b) -> m b
  ...
    -- Defined in ‘GHC.Base’
infixl 1 >>=

That's just the way it's defined. + is left-associative too, although the (addition-) group laws demand associativity.

Prelude> :i +
class Num a where
  (+) :: a -> a -> a
  ...
    -- Defined in ‘GHC.Num’
infixl 6 +

All an infixl declaration means is that the compiler will parse a+b+c as (a+b)+c; whether or not that happens to be equal to a+(b+c) is another matter.

the monad law demands associativity

Well, >>= is actually not associative. The associative operator is >=>. For >>=, already the type shows that it can't be associative, because the second argument should be a function, the first not.

Besides, monads encode a value dependency by making the next effect depend on the result of the previous one

Yes, but this doesn't contradict associativity of >=>. Example:

teeAndInc :: String -> Int -> IO Int
teeAndInc name val = do
   putStrLn $ name ++ "=" ++ show val
   return $ val + 1
Prelude Control.Monad> ((teeAndInc "a" >=> teeAndInc "b") >=> teeAndInc "c") 37
a=37
b=38
c=39
40
Prelude Control.Monad> (teeAndInc "a" >=> (teeAndInc "b" >=> teeAndInc "c")) 37
a=37
b=38
c=39
40

Flipping around the parens does not change the order / dependency between the actions (that would be a commutativity law, not an associativity one), it just changes the grouping of the actions.

leftaroundabout
  • 117,950
  • 5
  • 174
  • 319
  • OK, I think I do understand it a bit better. Function composition in math is associative whereas application is left associative. By using kleisli composition we can defer the application and thus remain associative. –  Sep 07 '20 at 15:03
  • Y...yeah. But FTR, associativity of Kleisli composition does _not_ automatically follow from the fact that Kleislis are functions. – leftaroundabout Sep 07 '20 at 15:14
  • 5
    @scriptum: I think you’re just mixing up two concepts of “associativity” here: [operator associativity](https://en.wikipedia.org/wiki/Operator_associativity) and the [associative property](https://en.wikipedia.org/wiki/Associative_property). “`>>=` is *left-associative*” just means `a >>= b >>= c` is *parsed* as `(a >>= b) >>= c`, which is just for convenience, to avoid having to write some parentheses. We could declare it `infix 1 >>=` instead. Whereas “`>=>` is *associative*” means that `(a >=> b) >=> c` is *equal* to `a >=> (b >=> c)`, a much stronger statement about the actual semantics. – Jon Purdy Sep 07 '20 at 19:36