Global variables

From HaskellWiki
Revision as of 13:40, 17 February 2009 by Adrian Hey (talk | contribs) (Deleting link to irrelevant haskell cafe post. This is *not* an example of the use of the "unsafePerformIO hack" under discussion.)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Question

Is there a simple and straightforward way to use global variables in Haskell?

Answer

(Perhaps annoyingly) the answer to this question, like so many other frequently asked questions, is a question. "What are you trying to do?"

The reason for this is that haskell's abstractions are different from those of the mainstream imperative languages, and the mapping isn't 1-1. So for a particular 'C' feature, there may be 3 or 4 haskell features which achieve similar effects, and the correct choice depends on the detailed context.

So, in particular, all those tasks which you use global variables for in C, can be achieved in haskell, but which solution depends what you are trying to do:

  1. If you have some globals which are constant, then just define them at the top level. No problem.
    pi = 3.14
    progname = "MyCoolApp"
  2. If you have a global environment, which various functions read from (and you might, for example, initialise from a configuration file) then you should thread that as a parameter to your functions (after having, very likely, set it up in your 'main' action). If the explicit parameter passing annoys you, then you can 'hide' it with a Monad.
  3. If you have a need to store some global state which various of your functions modify, then you have a design issue. This style of design is frowned upon in C as well! The correct solution in C is to pass a 'bundle' of appropriate parameters (you might call it an environment) to those functions which need it. In C++, perl or python you'd very likely make this bundle an object. In haskell this bundle will be a data value in some custom type; and using Monads you can 'hide the details' of passing it around, if you wish.

Source

Meanwhile, back on Earth

  • John Hughes has a Functional Pearl which advocates the use of implicit parameters for global variables. He also mentions the unsafePerformIO hack and the use of a Reader monad transformer, none of which are totally satisfactory: Global Variables in Haskell (2004)