I would imagine that the overall answers to this will push me over to Functional Reactive Programming, but... bear with me for a bit.
I also don't have example code for this question. I have wandered near the topic with some of my code, but I have stayed firmly in the IO monad with it.
Imagine that I have an application in which I am modelling somewhat complex state and put it into an overall Application State monad. I am doing it this way because I am wanting a certain level of detachment between my core application and the particular user interface.
data S = S DataStore EventStream Sockets
type AppState m = StateT S m
(assume that DataStore, EventStream, and Sockets are all data types that do basically what they sound like :))
Now, say I want to create a table in GTK (TreeView, but no child nodes) that views only the EventStream. I have already learned to do that by saying listStoreNew event_stream >>= treeViewNewWithModel (see http://markus.alyra.org/?p=1023 where I talked pretty extensively about the mechanics of setting this up).
But, now I have a mutable copy of data that is in my AppState monad. When the application goes off and does something that appends new data to the EventStream, that will not show up in the view. The only way I can think of it make it show up in the view is to send it over with a message like listStoreInsert my_new_event in addition to the changes made to the monad. That's doable, but is starting to feel clumsy.
Worse, though, this mythical tree view is an administrative view! It's editable! The admin says "oh, that event has some invalid data, I want to change it!". Now, I have no problems changing the data that is in the ListStore I created above. I can create callbacks that make the update with no problem. But I cannot think at all of how to get the update into the Global AppState Monad.
And those last few words show the core of the problem. If I have a global AppState Monad, then anything that updates that monad has to be in one line of execution with everything that wants to view the monad. The TreeView breaks that. When a cell gets edited in the TreeView monad, the edit handler runs entirely in the IO monad and is expected to return nothing. The end data type is IO (). Even if I had some nifty way to unwrap data from my AppState, then do the edit handler, and then re-wrap the data in my AppState, no other branch of the application could see it.
Even if I can figure out how to create my own completely custom ModelView instance that provides a read-only view into my AppState, I cannot think of how to make state updates available to the rest of the application.
So...
Is it even possible to model GTK/Haskell application in this way? Or, have I gone down the road to madness?