[Haskell-cafe] What unsafeInterleaveIO is unsafe
jonathanccast at fastmail.fm
Sun Mar 15 19:47:27 EDT 2009
On Mon, 2009-03-16 at 00:14 +0100, Daniel Fischer wrote:
> 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.
As is unsafeInterleaveIO. (And as is unsafePerformIO, as per the docs:
> If the I/O computation wrapped in unsafePerformIO performs side
> effects, then the relative order in which those side effects take
> place (relative to the main I/O trunk, or other calls to
> unsafePerformIO) is indeterminate.
> > > 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.
This version of those docs:
leaves unsafeInterleaveIO completely un-documented. So I'm still not
sure what you're quoting from.
> > 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.
Right. But by using forkIO or unsafeInterleaveIO you waive that
> > > 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.
[Ignored: begging the question]
More information about the Haskell-Cafe