
Nick Name wrote: | 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. But Hal Daume III's suggestion has that same problem: | data Configuration = ... -- config data | | globalConfig :: IORef Configuration | globalConfig = unsafePerformIO (newIORef undefined) : | getConfig :: Configuration | getConfig = unsafePerformIO $ readIORef globalConfig : | main = do | ...read configuration from file...no calls to getConfig... | writeIORef globalConfig configuration | doStuff | return () Imagine "globalConfig" being evaluated twice! This means there will be *two* IORefs in your program; one might be initialized, and not the other. This is even more disastrous. (To see what could happen: just inline the definition of globalConfig into the two places where it is used.) This is why one has to be EXTREMELY careful when using these kinds of constructs. Really, only use unsafePerformIO when you know what you are doing, and otherwise, leave it to someone else who can wrap it up into a nice, pure library. In general, when using unsafePerformIO in this way, one wants to tell the compiler that it is not allowed to inline the expression. This can be done in most compilers by giving compiler pragma's. /Koen. -- Koen Claessen http://www.cs.chalmers.se/~koen Chalmers University, Gothenburg, Sweden.