DiffArray Performance

Glynn Clements glynn.clements at virgin.net
Fri Nov 7 14:45:31 EST 2003

Stefan Reich wrote:

> > DiffArray is an example of a good use for unsafePerformIO: it uses
> > imperative operations to implement a pure API.  The DiffArray is made of
> > mutable objects under the hood, but as far as the programmer is
> > concerned it behaves just like a pure Array.
> I'd like to ask a general question about unsafePerformIO: What exactly 
> does unsafe mean? Just "impure" or rather "may lead to all kinds of 
> problems, you better don't use this"?

Essentially both. Haskell assumes purity (referential transparency),
so impurity is likely to result in "all kinds of problems".

If you think of the IO monad as a state transformer, i.e.

	IO a = World -> (World, a)

unsafePerformIO basically applies the transformation to whichever
World value happens to be available at the time (i.e. the current
system state, where "current" is unspecified), and that depends upon
the details of the evaluation mechanism.

Using unsafePerformIO is safe if the transformer generates the same
result result for all possible World values. If it generates different
results for different World values, you risk running into problems.

Note: even if you are willing to accept one of many possible "valid"
values, you need to allow for the fact that the expression may be
evaluated multiple times. E.g. if you have:

	let x = unsafePerformIO foo

where foo may produce different values, you could find that x /= x.

The opposite problem is also possible, i.e. that distinct occurrences
of the same expression could be merged. A common example is in
attempting to create "global variables":

	x, y :: IORef Int
	x = unsafePerformIO $ newIORef 0
	y = unsafePerformIO $ newIORef 0

Due to optimisation, x any y may end up referring to the same IORef.

In short: Haskell assumes referential transparency; if you break it,
all bets are off.

Glynn Clements <glynn.clements at virgin.net>

More information about the Glasgow-haskell-users mailing list