
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. -- In friendship, prad ... with you on your journey Towards Freedom http://www.towardsfreedom.com (website) Information, Inspiration, Imagination - truly a site for soaring I's

prad
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 myGameLoop when iWantToAbort $ abort () I hope this helps. Greets, Ertugrul -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://ertes.de/

On Wed, 11 Aug 2010 22:25:45 +0200
Ertugrul Soeylemez
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
thank you ertugrul. i understand the explanations you and MAN have provided regarding global variables. however, i don't understand what you have done above despite the illustrative game example. i've been in the middle of trying to get info out of a monad (as indicated in other posts) and have finally gotten by the errors (although the understanding hasn't quite congealed yet). as a result i haven't been able to try to incorporate the above yet (which is why i haven't responded till now). i did note that MonadLib doesn't seem to exist, so is that something i get from cabal? is ask part of it too?
What you want is not a global variable, but a convenient way to pass environment values to functions and computations.
yes that is what i want, but i haven't gotten the gist of the code you have provided me with yet. i need to understand types better for one thing.
I hope this helps.
it will. i've flagged your post and will come back to it after acquiring a bit more competence - as well as repetitive readings. -- In friendship, prad ... with you on your journey Towards Freedom http://www.towardsfreedom.com (website) Information, Inspiration, Imagination - truly a site for soaring I's

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 8/15/10 14:04 , prad wrote:
i did note that MonadLib doesn't seem to exist, so is that something i get from cabal? is ask part of it too?
MonadLib is on Hackage, yes. "ask" is part of the MonadReader typeclass. - -- brandon s. allbery [linux,solaris,freebsd,perl] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.10 (Darwin) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkxoQyEACgkQIn7hlCsL25XuZgCfQy4+KGvThqmFh0DPpfAEph/K bqEAn0Dmc0LnW40SMtblE6Jnl3AQWHJP =ldlg -----END PGP SIGNATURE-----

On 15 August 2010 20:42, Brandon S Allbery KF8NH
On 8/15/10 14:04 , prad wrote:
is ask part of it too?
"ask" is part of the MonadReader typeclass.
as a side note, asking hoogle might help in such questions: http://www.haskell.org/hoogle/?hoogle=ask hth, Ozgur

Brandon S Allbery KF8NH
On 8/15/10 14:04 , prad wrote:
i did note that MonadLib doesn't seem to exist, so is that something i get from cabal? is ask part of it too?
MonadLib is on Hackage, yes. "ask" is part of the MonadReader typeclass.
In MonadLib the class is named ReaderM, not MonadReader. Greets, Ertugrul -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://ertes.de/

There are no global variables in Haskell... You can have the names in the widest namespace, but there's no modification allowed. Whether you define your connection in the main, or at top (module) level, when you pass it to a function, it'll be copied. In your example code your defining a function 'fn' which has this signature: fn :: Connection -> a -> IO b But the Connection that 'fn' gets is a parameter, not a global. Ertugrul's approach is the correct one: you define your functions letting the transformers take care of the plumbing, and the params get passed around for you. El mié, 11-08-2010 a las 12:54 -0700, prad escribió:
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.

On 11 Aug 2010, at 20:54, prad 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 = ...
I too am interested in this.... Right now the best way to me seems to be to use StateT (I am mainly using SQLite). G
participants (6)
-
Brandon S Allbery KF8NH
-
Ertugrul Soeylemez
-
Gaius Hammond
-
MAN
-
Ozgur Akgun
-
prad