Richard Uhtenwoldt wrote: > (2) the global variable has a lexical scope that extends over > the bulk of the program.
> It strikes me as a simple and obvious application of lexical > scope, and I am surprised that it received no mention in the > discussions on this list and in Hughes's paper. Something like that has been mentioned before: http://www.haskell.org/pipermail/haskell-cafe/2002-September/003423.html If the global variables are used to store parameters that are read from configuration files at the beginning and are not changed since, it's possible to make such "global variables" _ordinary_ top-level variables scoped through the entire program. No unsafe operations, no pragmas, no implicit variables, and no reliance on the IO monad for variable access are needed. The previous article said the approach was ugly. I'd like to take it back. The approach relies on an ability to dynamically compile and link in a program -- something that we all do and something that is specifically emphasized in the GHCi documentation. The following code is snipped from the previous article and adjusted for GHC. The latter is used as a meta-evaluator/dynamic linker of sorts. Suppose file '/tmp/a.hs' contains the following user program. Suppose the program needs a global, configurational variable named Config.config_item. >>> File "/tmp/a.hs" > import Config (config_item) > > foo = "foo shows: " ++ (show config_item) > > bar = "bar shows: " ++ (show config_item) > > main = do > print foo > print bar > print foo Realistically a user program would do something more with the global variables than just showing them. We specifically illustrate multiple access to the global variable, to indicate that such access poses no trouble (in contrast to the unsafePerformIO approach). We also note that user computations 'foo' and 'bar' do not have to be annotated with the type and the name of the global variable -- in contrast to the implicit variable approach. Furthermore, foo and bar are pure functions rather than IO actions. The value of the global variable Config.config_item is computed by reading it from the configuration file. The computation occurs before running of the main function of the user program. The following code accomplishes the trick *>>> File "/tmp/b.lhs" *>>> To run this code, do *>>> ghci -package posix b.lhs *>>> Be sure /tmp/config exists and contains an integer value > import System (system, ExitCode(ExitSuccess)) > import Posix(executeFile) > > myconfig_file = "/tmp/config" > > phaseII_var = "/tmp/Config.hs" > phaseII_const = "/tmp/a.hs" > phaseII_eval = "ghc --make " > phaseII_result = "/tmp/a.out" > > nl = "\n" > > writeConfig :: Int -> IO () > writeConfig num = > do > writeFile phaseII_var $ > concat > ["module Config (config_item) where", nl, > "config_item =", show num, nl] > > > runSuperIO () = system (phaseII_eval ++ > phaseII_const ++ " -o " ++ phaseII_result) > >>= \ExitSuccess -> > executeFile phaseII_result False [] Nothing > > main = readFile myconfig_file >>= writeConfig . read >>= runSuperIO We can indeed be sure that the configurational variable is set before the first attempt to access it. _______________________________________________ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe