
Hal Daume III suggested: | 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 () In this case, there is no need to use unsafePerformIO more than once, nor does one need IORefs. Here is how: data Configuration = ... -- config data getConfig :: Configuration getConfig = unsafePerformIO $ do ...read configuration from file... return configuration main = do doStuff We know getConfig will only be evaluated once (because of sharing) (*) Don't use the dirty stuff when you do not have to! :-) I think GHC even supports a function getArgs which is not in the IO monad since the arguments to a program do not change during a program. If getConfig only depends on the arguments, no unsafePerformIO is necessary at all. Gofer, and even early versions of Hugs, had a function openFile :: FilePath -> String. Thge rationale was (I guess) that the contents of a file would not change during the evaluation of a Gofer program. Regards, /Koen. (*) Actually, a Haskell compiler is free to inline these kind of expressions, so really one has to give a NOINLINE pragma to the compiler as well. -- Koen Claessen http://www.cs.chalmers.se/~koen Chalmers University, Gothenburg, Sweden.