Iavor Diatchki 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
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
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 .
Haskell-Cafe mailing list