State monads don't respect the monad laws in Haskell
S.M.Kahrs
S.M.Kahrs@ukc.ac.uk
Tue, 14 May 2002 20:15:02 +0100
> "S.M.Kahrs" wrote:
> [snip]
> > I don't think this really solves the problem with the left unit
> > (not in general, and not for IO either),
> > it merely pushes it to a different place.
> [snip]
> Not being a category theorist I find this all a bit confusing.
Nothing to do with category theory.
I took the law you cited and checked it out.
> Can you
> give an example where with GHC and the fix I suggested you can show tha=
t
> the associative law has been broken?
I didn't try to find a counter example.
I tried to prove the result and got stuck:
This is the law I was stuck with:
m >>=3D (\x -> k x >>=3D h) =3D=3D=3D (m >>=3D k) >>=3D h =
There were two cases to consider, m=3DR a, and m=3DM a - the former works=
out nicely,
but with the latter you get:
m >>=3D (\x -> k x >>=3D h)
=3D M a >>=3D (\x -> k x >>=3D h)
=3D M (a >>=3D \a'->case (\x -> k x >>=3D h) a' of
R b -> return b
M c -> c)
=3D M (a >>=3D \a'->case (k a' >>=3D h) of
R b -> return b
M c -> c)
and on the other side:
(m >>=3D k) >>=3D h =
=3D (M a >>=3D k) >>=3D h
=3D M (a >>=3D \a'->case k a' of
R b -> return b
M c -> c) >>=3D h
=3D M ((a >>=3D \a'->case k a' of
R b -> return b
M c -> c) >>=3D \a''->case h a'' of
R b -> return b
M c -> c)
Assuming that the associativity law holds for the original monad
(the one we try to fix for its dodgy left unit) then this can be changed =
to:
M (a >>=3D \a' -> (\a'->case k a' of
R b -> return b
M c -> c) a' >>=3D \a''->case h a'' of
R b -> return b
M c -> c)
=3D M ((a >>=3D \a' -> case k a' of
R b -> return b
M c -> c) >>=3D \a''->case h a'' of
R b -> return b
M c -> c)
Using associativity again:
=3D M (a >>=3D \x->(\a' -> case k a' of
R b -> return b
M c -> c)x>>=3D(\a''->case h a'' of
R b -> return b
M c -> c))
=3D M (a >>=3D \a' -> (case k a' of
R b -> return b
M c -> c) >>=3D \a''->case h a'' of
R b -> return b
M c -> c)
Assuming further that >>=3D is left-strict we can change that to:
=3D M (a >>=3D \a' -> (case k a' of
R b -> return b >>=3D \a''->...
M c -> c >>=3D \a''->...))
where the ... is twice the old case h a'' expression.
Now, this is the expression why I claimed the left-unit property of
the underlying monad would still show: if (return b>>=3Df) is the same
as f b (in the monad we try to fix) then the first part of this case
expression simplifies to exactly the same thing as we had derived from th=
e
other side of the equation.
But if it does not hold, we should be able to construct a counter example=
using the left-unit counter example from the underlying monad together
with, say, k=3DR. This all under the assumptions that the original monad=
m
satisfied the assoc law and that its >>=3D is left-strict.
Stefan Kahrs