Dealing with configuration data

Koen Claessen koen@cs.chalmers.se
Thu, 26 Sep 2002 08:47:56 +0200 (MET DST)


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.