Simon Marlow simonmar@microsoft.com
Tue, 24 Sep 2002 13:58:40 +0100

> But it is a fact that many of us have at least some idea of
> what happens "under the hood" when we use unsafePerformIO.
> This is also described in your paper "Stretching the storage
> manager: weak pointers and stable names in Haskell".
> However, I for example have no idea what happens when
> unsafely executing something that throws exceptions,
> performs a forkIO, something that uses MVar's, etc.

Exceptions: an exception raised by the computation inside
unsafePerformIO will be propagated to the enclosing expression, as per
the normal semantics for imprecise exceptions.  The exception raised by
an application of unsafePerformIO may of course also be imprecise;
consider 'unsafePerformIO $ (1/0 + error "foo") `seq` return ()'.

The behaviour of forkIO and other side-effecting operations inside
unsafePerforIO can I think be explained by the following statement: if
an expression "unsafePerformIO e" has been reduced to head normal form,
then all the I/O computations in e have been performed.  The exact
timing of the evaluation is underspecified, just as any other expression
in Haskell.  However, if you're using unsafePerformIO with real side
effects, then I suspect that what you're doing is highly dodgy and you
should find another way to do it :-)

Does that help?

As for sharing, we currently don't provide any guarnatees, although we
should.  It is currently the case that if you write

a =3D unsafePerformIO (putStr "hello")
b =3D unsafePerformIO (putStr "hello")

and both a and b are evaluated, then you may get either one or two
"hello"s on stdout.  You can currently make things more deterministic by
(a) adding NOINLINE pragmas for a and b, and (b) using the flag -fno-cse
to disable common sub-expression elimination.  Then you'll get exactly
two instances of "hello" on stdout, although we won't guarantee that
behaviour for ever.  At some point we'll fix it so that unsafePerformIO
applications are never duplicated or coalesced.

If you're interested in when unsafePerformIO is "safe" to use, see:


(and see my followups for an alternative view).