
Iavor Diatchki wrote:
apfelmus wrote:
According to the monad law
f >>= return = f
every (>>=) ought to be strict in its first argument, so it indeed seems that the implementation given in the documentation is wrong.
From the monad law we can conclude only that "(>>= return)" is strict, not (>>=) in general.
Yes, I was too eager :)
For example, (>>=) for the reader monad is not strict in its first argument:
m >>= f = \r -> f (m r) r
So, "(undefined >> return 2) = (return 2)"
In other words, we have undefined >>= const (return x) = return x in the reader monad. Concerning the folklore that seq destroys the monad laws, I would like to remark that as long as we don't apply seq to arguments that are functions, everything is fine. When seq is applied to functions, already simple laws like f . id = f are trashed, so it's hardly surprising that the monad laws are broken willy-nilly. That's because seq can be used to distinguish between _|_ :: A -> B and \x -> _|_ :: A -> B although there shouldn't be a semantic difference between them. But it's true that in the case of evaluate , the monad laws are screwed up. The third equivalence would give evaluate _|_ >>= return ==> (return $! _|_) >>= return ==> _|_ >>= return and hence evaluate _|_ = _|_ which contradicts the first equivalence. In other words, it seems that in the presence of evaluate , the monad laws for IO are broken if we allow seq on values of type IO . Regards, apfelmus