[Haskell-beginners] Re: global variables
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
> 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):
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
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