adding state in GUIs (qtHaskell)

I'm trying to learn qtHaskell. I realize few people on this list know anything about qtHaskell, but I have a question that probably relates to all GUIs as implemented in Haskell. I just need a hint that could help me figure out the next step, which I might be able to infer from the qtHaskell API. I don't think is any tutorial-type or step-by-step type documentation for qtHaskell. I have sent some questions to the author of qtHaskell, David Harley, but he hasn't responded yet, and anyway I don't want to trouble him every time I have a question, so I'm trying to infer as much as I can. The problem relates to state. In Qt, one adds state to a widget by subclassing it and adding new member variables. For example, I want to create a widget that responds to keypresses and remembers what keypresses have taken place. I'm totally stuck on this part, because Haskell doesn't have state. There must be some kind of Haskell call that adds state to a widget, but it is hard to figure out from the qtHaskell examples David provides. Thanks, Mike

Been poking around. Maybe IORef has something to do with this? I found a qtHaskell example that seems to make use of IORef in order to accomplish something similar to what I want. Michael P Mossey wrote:
I'm trying to learn qtHaskell. I realize few people on this list know anything about qtHaskell, but I have a question that probably relates to all GUIs as implemented in Haskell. I just need a hint that could help me figure out the next step, which I might be able to infer from the qtHaskell API.
I don't think is any tutorial-type or step-by-step type documentation for qtHaskell. I have sent some questions to the author of qtHaskell, David Harley, but he hasn't responded yet, and anyway I don't want to trouble him every time I have a question, so I'm trying to infer as much as I can.
The problem relates to state. In Qt, one adds state to a widget by subclassing it and adding new member variables. For example, I want to create a widget that responds to keypresses and remembers what keypresses have taken place.
I'm totally stuck on this part, because Haskell doesn't have state. There must be some kind of Haskell call that adds state to a widget, but it is hard to figure out from the qtHaskell examples David provides.
Thanks, Mike _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Hello Michael, Thursday, September 10, 2009, 5:29:33 AM, you wrote:
I'm totally stuck on this part, because Haskell doesn't have state. There must
Haskell support states (yes, IORef is equal to C++ reference type - it's a constant pointer to some memory area that you may read/write), but it doesn't support OOP subclassing. this problem solved in different ways in each particular haskell GUI -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com

One simple solution is to leave the state in Qt. As of Qt 4.2, in C++ you can use bool QObject::setProperty(const char * name, const QVariant & value) QVariant QObject::property(const char * name) const to set and get properties on any QObject (hence any QWidget). Since I believe these are (not yet) wrapped in QtHaskell, you can instead just create a widget that contains the state and just don't add it to a layout. Parent it to a widget and it will quietly disappear when its parent dies. If you want it to persist until you say so, don't parent it to anything (but then you might as well use Haskell for your state!) Dan Michael P Mossey wrote:
I'm trying to learn qtHaskell. I realize few people on this list know anything about qtHaskell, but I have a question that probably relates to all GUIs as implemented in Haskell. I just need a hint that could help me figure out the next step, which I might be able to infer from the qtHaskell API.
I don't think is any tutorial-type or step-by-step type documentation for qtHaskell. I have sent some questions to the author of qtHaskell, David Harley, but he hasn't responded yet, and anyway I don't want to trouble him every time I have a question, so I'm trying to infer as much as I can.
The problem relates to state. In Qt, one adds state to a widget by subclassing it and adding new member variables. For example, I want to create a widget that responds to keypresses and remembers what keypresses have taken place.
I'm totally stuck on this part, because Haskell doesn't have state. There must be some kind of Haskell call that adds state to a widget, but it is hard to figure out from the qtHaskell examples David provides.
Thanks, Mike _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Dan Weston wrote:
One simple solution is to leave the state in Qt.
As of Qt 4.2, in C++ you can use
bool QObject::setProperty(const char * name, const QVariant & value) QVariant QObject::property(const char * name) const
to set and get properties on any QObject (hence any QWidget).
Since I believe these are (not yet) wrapped in QtHaskell, you can instead just create a widget that contains the state and just don't add it to a layout. Parent it to a widget and it will quietly disappear when its parent dies. If you want it to persist until you say so, don't parent it to anything (but then you might as well use Haskell for your state!)
Dan
Thanks for the reply, Dan. I don't quite follow---you mean create a widget in C++? I can't find setProperty/property in qtHaskell. I would like to keep everything in Haskell, though.

On Wed, 2009-09-09 at 18:29 -0700, Michael P Mossey wrote:
I'm trying to learn qtHaskell. I realize few people on this list know anything about qtHaskell, but I have a question that probably relates to all GUIs as implemented in Haskell. I just need a hint that could help me figure out the next step, which I might be able to infer from the qtHaskell API.
Ultimately it's done by some kind of mutable state, either an IORef, MVar or a thread. On top of these you can layer nicer stuff like a state monad (with a 'runState' function that saves and restores from an IORef). A personal favourite of mine is having the GUI event handler post data over a channel to a thread. That thread reads from the channel and deals with the events. The state of the GUI app is then held as local parameters in that thread. Doing this of course requires that the GUI lib you're using can cope with normal Haskell (forkIO) threads. This is possible with gtk2hs, I don't know about the others. Duncan

Duncan Coutts wrote:
On Wed, 2009-09-09 at 18:29 -0700, Michael P Mossey wrote:
I'm trying to learn qtHaskell. I realize few people on this list know anything about qtHaskell, but I have a question that probably relates to all GUIs as implemented in Haskell. I just need a hint that could help me figure out the next step, which I might be able to infer from the qtHaskell API.
Ultimately it's done by some kind of mutable state, either an IORef, MVar or a thread.
On top of these you can layer nicer stuff like a state monad (with a 'runState' function that saves and restores from an IORef).
A personal favourite of mine is having the GUI event handler post data over a channel to a thread. That thread reads from the channel and deals with the events. The state of the GUI app is then held as local parameters in that thread.
Doing this of course requires that the GUI lib you're using can cope with normal Haskell (forkIO) threads. This is possible with gtk2hs, I don't know about the others.
Hi Duncan, thanks for the reply. Can you point me to some code examples that do these things? -Mike

Michael Mossey wrote:
Duncan Coutts wrote:
On Wed, 2009-09-09 at 18:29 -0700, Michael P Mossey wrote:
I'm trying to learn qtHaskell. I realize few people on this list know anything about qtHaskell, but I have a question that probably relates to all GUIs as implemented in Haskell. I just need a hint that could help me figure out the next step, which I might be able to infer from the qtHaskell API.
Ultimately it's done by some kind of mutable state, either an IORef, MVar or a thread. In wxHaskell, the 'simplest' way to code this looks something like the following (literate Haskell)
Structure containing 'state' of all of the GUI objects
data UIState = UIState { uiConnect :: Button () , uiPort :: TextCtrl () , uiUser :: TextCtrl () , uiPasswd :: TextCtrl () , uiSandbox :: TextCtrl () , uiClients :: ComboBox () , uiChanges :: SingleListBox () , uiChangeInfo :: TextCtrl () , uiOrigin :: TextCtrl () , uiUpdate :: TextCtrl () , uiFrame :: Frame () }
uiState = unsafePerformIO $ newMVar (Nothing :: Maybe UIState)
Ensure that we initialize exactly once...
uiInitState bt pt us pw sb cl ci ch or up f = takeMVar uiState >>= \st -> case st of Nothing -> let st' = UIState bt pt us pw sb cl ci ch or up f in putMVar uiState (Just st') Just _ -> return ()
Get the mutable state. Note that in the error case we deliberately do not put the MVar back, as a means to block all threads waiting on the MVar (as this would indicate a general programming/threading issue to be identified).
getMVarState mv txt = takeMVar mv >>= \may_st -> case may_st of Nothing -> error (txt ++ " is not available") Just st -> putMVar mv may_st >> return st
Fetch the UI state - this will fail fatally if we fetch before state is initialized
uiGetState = getMVarState uiState "UI state"
I don't have anything as neat to show you as Duncan's suggetion (I'd also be interested to see a cleaner way to do it - this sort of code always grates a little with me, although all of the major Haskell GUI bindings seem to need a similar programming style. However, at the most basic 'trying it out' level, I suspect that something very like this will work just as well for qtHaskell as it does for wxHaskell.
On top of these you can layer nicer stuff like a state monad (with a 'runState' function that saves and restores from an IORef).
A personal favourite of mine is having the GUI event handler post data over a channel to a thread. That thread reads from the channel and deals with the events. The state of the GUI app is then held as local parameters in that thread.
Doing this of course requires that the GUI lib you're using can cope with normal Haskell (forkIO) threads. This is possible with gtk2hs, I don't know about the others. Regards Jeremy

On Fri, Sep 11, 2009 at 5:55 PM, Jeremy O'Donoghue < jeremy.odonoghue@gmail.com> wrote:
<snip>
I don't have anything as neat to show you as Duncan's suggetion (I'd also be interested to see a cleaner way to do it - this sort of code always grates a little with me, although all of the major Haskell GUI bindings seem to need a similar programming style.
However, at the most basic 'trying it out' level, I suspect that something very like this will work just as well for qtHaskell as it does for wxHaskell. Regards Jeremy
Very interesting code. However, I'd be very curious to see if qthaskell handles .ui files. And how it does. With C++, thanks to the 'uic' command line tool, we generate a class from the .ui file, and then just have to store an instance of it in our window/dialog/widget/whatever. This class has a setupUI member function, taking a QWidget*/QDialog*/QMainWindow*/whatever, which initializes all the ui components and put them on our widget just like we asked it to do in the designer. Actually, I'm wondering how the trick could be done (and if it is already done ?) in Haskell without letting too much things generated and compiled at the C++ level with some FFI magic. -- Alp Mestan http://blog.mestan.fr/ http://alp.developpez.com/

* Duncan Coutts
A personal favourite of mine is having the GUI event handler post data over a channel to a thread. That thread reads from the channel and deals with the events. The state of the GUI app is then held as local parameters in that thread.
Doing this of course requires that the GUI lib you're using can cope with normal Haskell (forkIO) threads. This is possible with gtk2hs, I don't know about the others.
I also would be happy to see some code. Recently I need to write a small app in gtk2hs which had to deal with state. I used Reader monad with IORef's in it, but got tired of mixing code in different monads. (It would help, btw, if gtk2hs functions were not in IO, but in MonadIO). So I'm curious how 'gtk2hs app done right' looks like. -- Roman I. Cheplyaka :: http://ro-che.info/ "Don't let school get in the way of your education." - Mark Twain
participants (8)
-
Alp Mestan
-
Bulat Ziganshin
-
Dan Weston
-
Duncan Coutts
-
Jeremy O'Donoghue
-
Michael Mossey
-
Michael P Mossey
-
Roman Cheplyaka