# The Proper Definition of (evaluate :: a -> IO a)

Malcolm Wallace Malcolm.Wallace at cs.york.ac.uk
Mon May 7 12:54:04 EDT 2007

Nils Anders Danielsson <nad at cs.chalmers.se> wrote:

> > Where did you find the erroneous version?
> Presumably he found it by reading the documentation for evaluate:

Actually, I checked the source code for Control.Exception before asking
the question, and those laws definitely do not appear there.  So now I'm
kind of puzzled as to how Haddock managed to generate documentation for
them!

> >> evaluate x `seq` y    ==>  y
> >
> > I'm not sure why anyone thinks this "law" should hold,
>
> You seem to be assuming that evaluate x = x, which is not
> necessarily the case.

Yes, I did make a mistake when I asked the question, in assuming some
intuitive semantics rather than the actually written ones.  So taking
the law at face value, it seems to say that 'evaluate' is supposed to
force its argument, yet the result should be guaranteed to be in WHNF,
even if the argument was in fact undefined.  Given that the result is in
the IO monad, it can only mean one of two things:

(1) That 'evaluate' should _not_ force its argument when it is called,
but that rather that the argument should be forced only when the
resultant IO action is executed.  This conflicts with the
documentation, which implies that the argument is forced _before_
the IO action is created or executed.  But I guess this semantics
accords with Isaac's suggested definition:
evaluate x = (x `seq` return x) >>= return

(2) A constraint on the internal representation of IO computations,
such that it must implement imprecise exceptions.  Thus, 'evaluate'
could catch any exception caused by undefinedness in its argument,
and wrap it up as a defined value again,  e.g.
evaluate x = (x `seq` return x)
`catch` (\e-> IO (\world-> (x,world)))
Hmm, actually this _also_ has the property of delaying when x is
forced to the moment of execution of the result.  Maybe
evaluate x = (x `seq` return x) `FATBAR` return x
or something otherwise not expressible in Haskell without extra
primitives?  Of course, perhaps 'evaluate' is itself supposed to
be primitive.

I'm not sure I have expressed my reasoning very clearly, but either
way, some clarification would be welcome.

Regards,
Malcolm