State monads don't respect the monad laws in Haskell

Simon Marlow simonmar@microsoft.com
Tue, 14 May 2002 12:14:02 +0100


An interesting revelation just occurred to Simon P.J. and myself while
wondering about issues to do with exceptions in the IO monad (see
discussion on glasgow-haskell-users@haskell.org if you're interested).

The question we were considering was whether the following should hold
in the IO monad:

	(return () >>=3D \_ -> undefined) `seq` 42   =3D=3D  undefined

as we understand the IO monad it certainly shouldn't be the case.  But
according to the monad laws:

	(law)  return a >>=3D k  =3D=3D  k a
	so     (return () >>=3D \_ -> undefined) `seq` 42
      =3D>     ((\_ -> undefined) ()) `seq` 42
      =3D>     undefined `seq` 42
	=3D>     undefined

So the IO monad in Haskell, at least as we understand it, doesn't
satisfy the monad laws (or, depending on your point of view, seq breaks
the monad laws). =20

This discrepancy applies to any state monad.  Suppose we define

	return a =3D \s -> (s, a)
	m >>=3D k =3D \s -> case m s of (s', a) -> k a s'

now
	   return a >>=3D k
      =3D> \s -> case (return a) s of (s', a') -> k a' s'
	=3D> \s -> case (s, a) of (s', a') -> k a' s'
	=3D> \s -> k a s

	but (\s -> k a s) /=3D (k a) in Haskell, because seq can
	tell the difference.

What should the report say about this?

Cheers,
	Simon