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