Sometimes I wish there was a global variable

Hello, I am writing a OpenGL program in haskell, it can be found in: http://github.com/aflag/galo/tree/master But I hope this e-mail will be self-contained :). My main function goes like this: (...) rotX <- newIORef (0.0::GLfloat) rotY <- newIORef (0.0::GLfloat) pos <- newIORef (0.0::GLfloat, 0.0, 0.0) displayCallback $= display (map f range) rotX rotY pos keyboardMouseCallback $= Just (keyboardMouse rotX rotY pos) (...) Notice that rotX, rotY and pos are meant to be used as comunication between the keyboardMouse and display functions. They need to be set as 0 first, so display won't do anything. Only when they user press a few buttons that those values change, so display behaves accordanly. In a state-based language I would place display and keyboardMouse in one module and let them communcate to each other like they want. In haskell, I'm not quite sure how to do it except by that parameter passing style. I thought about how state-monad may help with that. But I'm not sure how I'd make the state variable to be contained inside a display/keyboardMouse module. []'s Rafael

Notice that rotX, rotY and pos are meant to be used as comunication between the keyboardMouse and display functions. They need to be set as 0 first, so display won't do anything. Only when they user press a few buttons that those values change, so display behaves accordanly.
In a state-based language I would place display and keyboardMouse in one module and let them communcate to each other like they want. In haskell, I'm not quite sure how to do it except by that parameter passing style.
In one module, you can write: ---------- giveMeFunctions = do { newIORef ... newIORef ... newIORef ... (...) let f1 = ... let f2 = ... return (f1,f2) ---------- and in the main: (keyboardMouse,display) <- giveMeFunctions Best, Maurício

Maurício wrote:
Notice that rotX, rotY and pos are meant to be used as comunication between the keyboardMouse and display functions. They need to be set as 0 first, so display won't do anything. Only when they user press a few buttons that those values change, so display behaves accordanly.
In a state-based language I would place display and keyboardMouse in one module and let them communcate to each other like they want. In haskell, I'm not quite sure how to do it except by that parameter passing style.
In one module, you can write:
---------- giveMeFunctions = do { newIORef ... newIORef ... newIORef ... (...) let f1 = ... let f2 = ... return (f1,f2) ----------
and in the main:
(keyboardMouse,display) <- giveMeFunctions
Doing it like that I could have all the definitions in one module, but it doesn't solve another important problem: keyboardMouse and display functions have to have as many parameters as there are IORefs. In my particular case, since I find out what key the use has pressed through pattern matching, keyboardMouse has several definitions. So adding a new IORef means adding a wildcard parameter to each keyboardMouse definition. As well as a new parameter to the display function. Which looks a bit clumbersome to me. In a state-based language I'd have something in the lines of: switch (key) { case LEFT_KEY : /* using var1 ... */ case RIGHT_KEY : /* using var2 ... */ } then, handling a new case would be a matter of adding a global variable and adding a new case in the end of the function containing the switch. Whereas in Haskell I would have something like keyboard var1 _ LeftKey = ... keyboard _ var2 RightKey = ... If I wanted to add a new IORef I'd have to do something like: keyboard var1 _ _ LeftKey = ... keyboard _ var2 _ RightKey = ... keyboard _ _ var3 RightKey = ... So, I had to change all previous definitions.

On Sun, Mar 22, 2009 at 08:10:28PM -0300, Rafael Cunha de Almeida wrote:
Doing it like that I could have all the definitions in one module, but it doesn't solve another important problem: keyboardMouse and display functions have to have as many parameters as there are IORefs.
You may always create a new data type.
Whereas in Haskell I would have something like keyboard var1 _ LeftKey = ... keyboard _ var2 RightKey = ... If I wanted to add a new IORef I'd have to do something like: keyboard var1 _ _ LeftKey = ... keyboard _ var2 _ RightKey = ... keyboard _ _ var3 RightKey = ... So, I had to change all previous definitions.
Initial code:
data Vars = Vars {var1 :: {-# UNPACK #-} !(IORef Type1) ,var2 :: {-# UNPACK #-} !(IORef Type2)}
keyboard v LeftKey = ... (var1 v) ... keyboard v RightKey = ... (var2 v) ...
Modified code:
data Vars = Vars {var1 :: {-# UNPACK #-} !(IORef Type1) ,var2 :: {-# UNPACK #-} !(IORef Type2) ,var3 :: {-# UNPACK #-} !(IORef Type3)}
keyboard v LeftKey = ... (var1 v) ... -- unchanged keyboard v RightKey = ... (var2 v) ... -- unchanged keyboard v OtherKey = ... (var3 v) ...
Note that the UNPACKs aren't really necessary. -- Felipe.

On 2009 Mar 22, at 19:10, Rafael Cunha de Almeida wrote:
Doing it like that I could have all the definitions in one module, but it doesn't solve another important problem: keyboardMouse and display functions have to have as many parameters as there are IORefs.
Or a single argument which holds all IORefs. Or record-style pattern matching:
If I wanted to add a new IORef I'd have to do something like: keyboard var1 _ _ LeftKey = ... keyboard _ var2 _ RightKey = ... keyboard _ _ var3 RightKey = ...
keyboard {v = var1} LeftKey = ... keyboard {v = var2} RightKey = ... -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

Ok, replying to the list this time. Darn Thunderbird not reading my mind again. Rafael Cunha de Almeida wrote:
Maurício wrote:
In one module, you can write:
---------- giveMeFunctions = do { newIORef ... newIORef ... newIORef ... (...) let f1 = ... let f2 = ... return (f1,f2) ----------
and in the main:
(keyboardMouse,display) <- giveMeFunctions
Doing it like that I could have all the definitions in one module, but it doesn't solve another important problem: keyboardMouse and display functions have to have as many parameters as there are IORefs.
I don't think so. I think M means the two functions are closures capturing all the IORefs, i.e. they know which IORefs they refer to. In OO terms, the two functions together are the two methods of an object that contains the IORefs as fields, and you needn't pass those IORefs in. Note that calling giveMeFunctions twice will get you two distinct "objects", not the same one twice. -- src/

Rafael Cunha de Almeida
My main function goes like this: (...) rotX <- newIORef (0.0::GLfloat) rotY <- newIORef (0.0::GLfloat) pos <- newIORef (0.0::GLfloat, 0.0, 0.0)
displayCallback $= display (map f range) rotX rotY pos
keyboardMouseCallback $= Just (keyboardMouse rotX rotY pos) (...)
...
In a state-based language I would place display and keyboardMouse in one module and let them communcate to each other like they want. In haskell, I'm not quite sure how to do it except by that parameter passing style.
You could try something like this: (and apologies in advance for any
typoes)
------------------------------------------------------------------------
import Control.Concurrent.MVar
data MyState = MyState {
rotX :: GLFloat
, rotY :: GLFloat
, pos :: (GLFloat,GLFloat)
}
myDisplayCallback :: MVar MyState -> IO ()
myDisplayCallback =
flip modifyMVar_ $ \(MyState rx ry p) -> do
(newRx, newRy, newP) <- yourCodeGoesHere
return $ MyState newRx newRy newP
main = do
mvar <- newMVar $ MyState 0 0 (0,0)
displayCallback $= myDisplayCallback mvar
...
------------------------------------------------------------------------
Cheers,
G.
--
Gregory Collins

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Rafael Cunha de Almeida wrote: | Hello, | | I am writing a OpenGL program in haskell, it can be found in: | http://github.com/aflag/galo/tree/master | But I hope this e-mail will be self-contained :). | | My main function goes like this: | (...) | rotX <- newIORef (0.0::GLfloat) | rotY <- newIORef (0.0::GLfloat) | pos <- newIORef (0.0::GLfloat, 0.0, 0.0) | | displayCallback $= display (map f range) rotX rotY pos | | keyboardMouseCallback $= Just (keyboardMouse rotX rotY pos) | (...) | | Notice that rotX, rotY and pos are meant to be used as comunication | between the keyboardMouse and display functions. They need to be set as | 0 first, so display won't do anything. Only when they user press a few | buttons that those values change, so display behaves accordanly. | | In a state-based language I would place display and keyboardMouse in one | module and let them communcate to each other like they want. In haskell, | I'm not quite sure how to do it except by that parameter passing style. | | I thought about how state-monad may help with that. But I'm not sure how | I'd make the state variable to be contained inside a | display/keyboardMouse module. Another way to do this would be something like this: ~ main = do ~ ... ~ displayCallback $= initialDisplayFunction ~ keyboardMouseCallback $= keyboardMouseFunction ~ ... ~ keyboardMouseFunction = do ~ rotX <- ... ~ rotY <- ... ~ pos <- ... ~ ... ~ displayCallback $= display ... rotX rotY rotZ You could even write your own state monad that does this callback reassignment for you (perhaps by wrapping StateT s IO a), then you can forget about all this explicit parameter passing. - - Jake -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAknHq+kACgkQye5hVyvIUKnX3ACeMLD8FLOTEya8can6veyp6cT3 ClMAnRdfl/DyOshvzlBF8QCtYgTf87fd =Bp4F -----END PGP SIGNATURE-----
participants (7)
-
Brandon S. Allbery KF8NH
-
Felipe Lessa
-
Gregory Collins
-
Jake McArthur
-
Maurício
-
Rafael Cunha de Almeida
-
Simon Richard Clarkstone