Is there a simple and straightforward way to use global variables in Haskell?
(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:
- If you have some globals which are constant, then just define them at the top level. No problem.
pi = 3.14
progname = "MyCoolApp"
- 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.
- 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.
- Jules Bean in Haskell Cafe
Meanwhile, back on Earth
- People have been known to use Top level mutable state, otherwise known as the "unsafePerformIO hack".
- 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)
- Edsko de Vries in Haskell Cafe on Just how unsafe is unsafe about how
unsafePerformIOfailed for global unique identifier generation.