
I just wrote a long and clear answer, but my e-mail client has crashed.
I am going to change it (or to rewrite one in Haskell, grrr) but the
answer will be shorter, I apologize.
On Wed, 25 Sep 2002 16:34:02 -0700 (PDT)
Hal Daume III
I don't mean to troll, but this isn't what I meant.
You aren't. I misunderstood you, of course.
now, we have doStuff :: IO a. doStuff is allowed (even in its pure methods) to use getConfig. I claim that this is safe. I could be wrong; this is only a hand-waiving argument. Why?
The first reference in the program to globalConfig is through a writeIORef. This means that at this point globalConfig gets evaluated and thus a ref is created. Immediately we put a value in it.
Now, when doStuff runs, since it is an action run *after* the call to writeIORef, provided that it doesn't also write to 'globalConfig' (which I mentioned in my original message), any call to getConfig is deterministic.
Even this appears correct, and I feel that it's a technique widely used in the haskell community, nothing prevents a global optimizer to evaluate all pure functions wich do not depend on a value obtained by IO *before the "main" function*. This is also stated in the GHC documentation, about "unsafePerformIO": "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." If getConfig is evaluated before the main function (nothing prevents it) and if all equal pure expressions are evaluated only once, readConfig will always lead to "undefined" (yes, it will always be evaluated after "globalConfig"). The first idea from Koen Claessen (getConfig operates directly on the file with unsafePerformIO) appears to work, but this time we are *relying* on the fact that the function will be evaluated once, since the file could change and multiple evaluations of readConfig wouldn't lead to the same result. This is not good anyway. Vincenzo