[Haskell-cafe] One-shot? (was: Global variables and stuff)

Adrian Hey ahey at iee.org
Thu Nov 11 04:16:04 EST 2004

On Thursday 11 Nov 2004 6:36 am, Judah Jacobson wrote:
> AFAIKS, the definition of "once" that I gave uses unsafePerformIO in a
> perfectly sound manner; namely, the creation of a top-level MVar.  It
> only becomes unsafe if certain "optimizations" are performed; but
> then, that's also true for the SafeIO proposal (as I understand it).

That's the trouble with unsafePerformIO. Haskell is supposed to be a
purely functional language and the compiler will assume all functions
are pure. As soon as you use unsafePerformIO to create something that
isn't a function you're in grave danger, even if it "looks safe" at
the local level, it still isn't a function and the damage can't be
contained at the local level. It's only really OK if it still is
a function despite the use of unsafePerformIO (which is possible,
but often hard to be sure about).

> Yeah, perhaps it hasn't been said so much before.  :-)   You noted
> several days ago that oneShot (a variant of my "once") can be defined
> using top-level mutable variables.  I was just pointing out that the
> converse is true: top-level mutable variables can be emulated using

I'm not too sure about that. But I guess the devil's in the detail,
so until that's been thrashed out I'll reserve judgement.

> Again, I would assume that any translation of (x <- someAction) needs
> to have a prohibition on CSE, inlining, etc on the RHS; there's
> nothing special to once here.

Yes, but the trouble is in Haskell if you have x = y that really means
any occurance of x can be replaced by y (and vice-versa) without changing
the meaning of the program (subject to scoping rules of course).

You're right that your once solution and the (x <- someAction) both have
the same problem. But the difference is the compiler doesn't know that
with the once solution because you've told it that..
 myRef = once (newIORef 'a')
..and it will believe you.

> I disagree that this only works for newIORef.  Consider (in ghci):

Well no, of course newIORef isn't the *only* case where it works :-)

But I thought the point you were making was that the once guaranteed
that the resulting value was independent of when it got reduced
(presumably for any action). This isn't generally true, any more
than it would be true for the x <- someAction solution if some
action can be *any* IO monadic operation.

That's why the proposal to use a restricted monad was put forward
I.E. an "IO monad" which was not capable of doing any real IO.
In principle at least, with the SafeIO/CIO monads the resulting
initial value could be determined at compile time, which is
exactly what we want I think (same intial value for every program

Adrian Hey

More information about the Haskell-Cafe mailing list