State monads don't respect the monad laws in Haskell

John Launchbury john@launchbury.org
Thu, 16 May 2002 09:58:07 -0700


Yes. Let me be clear.

It is not the fact that `seq` operates on functions that breaks foldr/build:
it is the fact that `seq` claims to be parametrically polymorphic when in
fact it is not. The parametricity result is weakened to the point that the
foldr/build proof no longer applies, and a counter example can be
constructed, viz.

  head = foldr const undefined
  one = build (\c n -> n `seq` c 1 n)

  result = head one

The one definition looks fine as the body to build is sufficiently
polymorphic, but that only because `seq` is lying.

John

>> I watched with interest the discussion about the ravages of `seq`.
>> 
>> In the old days, we protected uses of `seq` with a type class, to keep it at
>> bay. There was no function instance (so no problem with the state monads, or
>> lifting of functions in general), and the type class prevented interference
>> with foldr/build.
>> ...
> 
> Just a further remark: During discussion with Olaf about consequences of
> `seq` for foldr/build, respectively his type-inference based
> deforestation, I had the impression that there could very well be a
> function instance for `seq` not interfering with shortcut deforestation,
> provided this instance is restricted in the following way:
> 
> class Eval a where seq :: a -> b -> b
> 
> instance Eval d => Eval (c -> d)
> 
> I have no idea what would be a semantic justification for this instance
> declaration, except that it allows use of `seq` on at least some
> function types, but seems to outlaw all the critical cases where use of
> `seq` falsifies the foldr/build-rule.
> 
> 
> --
> Janis Voigtlaender