State monads don't respect the monad laws in Haskell

Jan-Willem Maessen jmaessen@alum.mit.edu
Tue, 14 May 2002 12:32:30 -0400


Dylan Thurston <dpt@lotus.bostoncoop.net> writes:
> I don't think this is necessarily wise to drop this from the report
> altogether.  To me, it seems comparable to associativity of addition
> for instances of Num; many instances don't satisfy it (e.g., Float),
> but it's a useful guideline to keep in mind.
>
> I've often been bothered by the inconsistent treatment of laws in the
> report; why are there laws for functors, monads, and quot/rem and
> div/mod, and not much else?  I'm pleased to see that the laws that are
> given actually do have exceptions.

Chalk me up as someone in favor of laws without exceptions.

Allow me for a moment to make a reductio argument: We should just make
Haskell into a strict language.  Our equational laws still hold 95% of
the time---after all, we don't really write non-terminating
computations that often, and that's where the laws break down.  And
gosh darn, we sure get an efficient implementation.

Of course, this argument doesn't really work out for the Haskell
constructs we know and love (monadic computations spring to mind given
the present conversation, along with certain uses of parsing
combinators, but I bet you can think of your own examples).

Having spent several years working with versions of Haskell with
weakened equational semantics, I have become a bit of a reactionary on
this point.  Sort-of equational semantics just aren't powerful enough
for many applications---we spend our time mired in the corner cases
(such as non-termination), which is exactly what we were trying to
avoid by using Haskell in the first place.

I can't stress that enough.  Freedom from crazy corner cases is
Haskell's big selling point.  None of this "except for infinite
computations" stuff.  None of this "as long as f has no side
effects".  If I have to worry about corner cases, I'm probably better
off adding type classes and beautiful syntax to OCaml.

That said, "seq" is a big wart on Haskell to begin with.  I might be
willing to allow "nice" rules like the monad laws to apply *as long as
the results are not passed (directly or indirectly) to seq*.  But I'm
not willing to go from "the IO monad disobeys the laws in the presence
of seq, and that might be OK" to "my monad disobeys the laws in code
that never uses seq, and that's OK because even IO breaks the monad
laws".  And I'd really much rather we cleaned up the semantics of
seq---or better yet, fixed the problems with lazy evaluation which
make seq necessary in the first place.  [Let me be clear: I believe
hybrid eager/lazy evaluation, the subject of my dissertation, does
eliminate the need for seq in most cases---so I'm a bit biased here.]

-Jan-Willem Maessen