[Haskell-cafe] What unsafeInterleaveIO is unsafe

Daniel Fischer daniel.is.fischer at web.de
Sun Mar 15 19:14:13 EDT 2009

Am Sonntag, 15. März 2009 23:30 schrieb Jonathan Cast:
> On Sun, 2009-03-15 at 23:18 +0100, Daniel Fischer wrote:
> > Am Sonntag, 15. März 2009 22:20 schrieb Jonathan Cast:
> > > There is *no* guarantee that main0 prints 0, while main1 prints 1, as
> > > claimed.  The compiler is in fact free to produce either output given
> > > either program, at its option.  Since the two programs do in fact have
> > > exactly the same set of possible implementations, they *are*
> > > equivalent. So the ordering in fact *doesn't* matter.
> >
> > Hum. Whether the programme prints 0 or 1 depends on whether "writeIORef r
> > 1" is done before "readIORef r".
> > That depends of course on the semantics of IO and unsafeInterleaveIO.
> >
> > In so far as the compiler is free to choose there, it can indeed produce
> > either result with either programme.
> > But I think
> > "Haskell 's I/O monad provides the user with a way to specify the
> > sequential chaining of actions, and an implementation is obliged to
> > preserve this order." (report, section 7) restricts the freedom
> > considerably.
> Why not read that line as prohibiting concurrency (forkIO) as well?

Good question.
Because forkIO is a way to explicitly say one doesn't want the one thing 
necessarily done before the other, I'd say.

> > However, I understand
> > "unsafeInterleaveIO allows IO computation to be deferred lazily. When
> > passed a value of type IO a, the IO will only be performed when the value
> > of the a is demanded."
> Where is this taken from?  If GHC's library docs try to imply that the

From the documentation of System.IO.Unsafe.

> programmer can predict when an unsafeInterleaveIO'd operation takes
> place --- well, then they shouldn't.  I'm starting to suspect that not
> starting from a proper denotational theory of IO was a major mistake for
> GHC's IO system (which Haskell 1.3 in part adopted).


> > as explicitly allowing the programmer to say "do it if and when the
> > result is needed, not before".
> Haskell's order of evaluation is undefined, so this doesn't really allow
> the programmer to constrain when the effects are performed much.

The full paragraph from the report:

" The I/O monad used by Haskell mediates between the values natural to a 
functional language and the actions that characterize I/O operations and 
imperative programming in general. The order of evaluation of expressions in 
Haskell is constrained only by data dependencies; an implementation has a 
great deal of freedom in choosing this order. Actions, however, must be 
ordered in a well-defined manner for program execution -- and I/O in 
particular -- to be meaningful. Haskell 's I/O monad provides the user with a 
way to specify the sequential chaining of actions, and an implementation is 
obliged to preserve this order."

I read it as saying that IO *does* allow the programmer to control when the 
effects are performed.

> > So I think main0 *must* print 0, because the ordering of the statements
> > puts the reading of the IORef before the result of the
> > unsafeInterleaveIOed action may be needed, so an implementation is
> > obliged to read it before writing to it.
> >
> > In main1 however, v may be needed to decide what action's result x is
> > bound to, before the reading of the IORef in the written order, so if f
> > is strict, the unsafeInterleaveIOed action must be performed before the
> > IORef is read and the programme must print 1,
> Although as Ryan pointed out, the compiler may decide to omit the case
> statement entirely, if it can statically prove that f v is undefined.

I suppose that's a typo and should be "unneeded".
But can it prove that f v is unneeded? After all, it may influence whether 0 
or 1 is printed.

> >  but if f is lazy, v is not needed for that
> > decision, so by the documentation, the unsafeInterleaveIOed action will
> > not be performed, and the programme prints 0.
> jcc

More information about the Haskell-Cafe mailing list