[Haskell-beginners] Re: global variables

Ertugrul Soeylemez es at ertes.de
Wed Aug 11 16:25:45 EDT 2010

prad <prad at towardsfreedom.com> wrote:

> i'm curious about the best way to deal with conn to make db
> connections.
> i define it in main like this, then when i want to use it in a
> function i have to pass it as a parameter:
> main = do
>     conn <- connectPostgreSQL ...
>     fn conn something
> fn conn x = ...
> now conn is a global variable i guess because it is defined in main,
> but perhaps main isn't considered a global namespace? i recall in
> python a global variable could be accessed by functions, but in php
> they can't unless you use "global" within the function.
> so is this the correct way to handle such things? right now it seems
> to be the only way in haskell.

I'd say the closest to a global variable in Haskell is a top level
definition.  However, that definition is fixed by the programmer and
cannot be changed at run time, of course.  What you want is not a global
variable, but a convenient way to pass environment values to functions
and computations.  My way of doing this is the following (snippet):

  import Control.Applicative
  import MonadLib

  type DatabaseT = ReaderT Connection

  myApplication :: DatabaseT IO ()
  myApplication = do
    dbConn <- ask
    inBase $ runRaw dbConn "SELECT now();"

  runDatabaseT :: BaseM m IO => DatabaseT m a -> m a
  runDatabaseT c = do
    conn <- inBase $ connectPostgreSQL ""
    runReaderT (Config conn) c

  main :: IO ()
  main = runDatabaseT myApplication

This is really convenient and useful for modularizing your code.  You
can easily write a monad transformer for every part of your program.
However, using this approach you will generally stick together multiple
state and reader monads together.  So it may be more convenient to use a
newtype instead of a type alias.  For example a game could look like
this (using newtypes for the individual transformers):

  type GameT m = ObjectsT (TextureT (SDLT (OpenGLT m)))

  runGameT :: BaseM m IO => GameT m a -> m a
  runGameT = runOpenGLT . runSDLT . runTextureT . runObjectsT

  myGame :: GameT IO ()
  myGame = do
    loadTexture "blah.jpg"
    addObject $ Player 0 0 0
    addObject $ Enemy 0 0 0
    runContT return . forever $ do
      when iWantToAbort $ abort ()

I hope this helps.


nightmare = unsafePerformIO (getWrongWife >>= sex)

More information about the Beginners mailing list