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

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 run). Regards -- Adrian Hey

On Thu, 11 Nov 2004 09:16:04 +0000, Adrian Hey
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).
Your first reply convinced me that supplying once as a function would be bad. I'm still not entirely convinced that hiding it in the compiler implementation of (x <- someAction) is infeasible, but as you say the devil's in the details. Even if it could be hacked to work, the added complexity is probably not worth it.
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.
Ok, I think that's where we diverged. I was trying to be more ambition and also consider actions such as reading in a configuration file, which seems to be another common use of unsafePerformIO. The idea behind "once" is that although the return value does depend on when it's reduced, this happens at a well-defined location (namely, where it first appears in the sequence of IO actions that makes up the program). But in any event, the proposal for oncePerString/Process/Type seems like a much a more robust solution than mine. Best, -Judah
participants (2)
-
Adrian Hey
-
Judah Jacobson