> I take it the position of those who object to such things is not.. > "Top level mutable variables are a very very bad thing and > should never ever be used (Errm..well unless they're really > necessary, in which case you should use C)."
more like: if you have two parts of your codebase, one of which easily accomodates such variables and is already flooded with them, the other not, then it may be a good idea to put such variables in the first part. but that doesn't mean that there aren't common programming problems that are currently inconvenient in Haskell and could be supported better, without the need for unsafePerformIO. > As I have observed in an earlier post, the thread title > chosen by the OP is a rather unfortunate choice of words IMO. > I wish people stop talking about "global variables". Nobody is > advocating the use of global mutable variables. perhaps you aren't, and some other posters in this thread aren't, but it is one of the most common uses of unsafePerformIO, and it is one of the subjects of this thread (and the ones before). then again, perhaps you're only thinking you're not talking about global mutable variables (the emphasis being more on mutable than on global). if you look back at your own oneShot example, you might find that the local MVar putting and taking isn't doing much at all, and the magic lies in the use of unsafePerformIO to share the result of the IO action. so you could move the unsafePerformIO into your oneShot (if you're certain to inspect the result of initialisation, you could avoid the strict application $!): Prelude System.IO.Unsafe> let realInit = putStrLn "okay" Prelude System.IO.Unsafe> let {oneShot :: IO a -> IO a; oneShot io = return $! unsafePerformIO io} Prelude System.IO.Unsafe> let userInit = oneShot realInit Prelude System.IO.Unsafe> userInit >>= print okay () Prelude System.IO.Unsafe> userInit >>= print () Prelude System.IO.Unsafe> userInit >>= print () Prelude System.IO.Unsafe> in other words, the core of your example is the variable userInit that is modified exactly once. but modified it is, even though userInit is a Haskell variable, no MVar or other inherently modifiable thing. depending on what realInit does (and being in IO a, that could be a lot), that may or may not be observable. and as others pointed out, reasoning about programs involving unsafePerformIO involves contextual equivalences, no longer replacing equals in all contexts, so hoping for referential transparency in the general case might be a bit optimistic (that's why one has to disable compiler optimisations based on this property, after all). your specific case seems slightly less problematic since userInit is itself of type IO (), but in combination with the monad laws, one might still run into trouble -- every use of unsafePerformIO indicates a proof obligation that such trouble will not arise (or rather: under what constraints it won't). > Actually, I know I'm not going to have to repeat this yet again > because I'm going to make this is my last post on this thread. as i said in my other post (waiting for moderator approval), there are many people on this thread, and i'm not sure they are all talking about the same thing. perhaps a good step forward would be for each concrete proposal to go into a separate thread (beginning with a summary of the use pattern to be covered and the concrete extension proposal claiming to do the job), and then to see whether there is any consensus for any of them. cheers, claus _______________________________________________ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe