I am trying to retain some state on my GUI application so that I may be able to construct a list of values from user input. But I have trouble understanding the State monad so...
Here is some test code to illustrate what I want (it is obvious it will not compile, haven't even tryed to) :
-- // --
main :: IO ()
main = do
initGUI
build <- builderNew
builderAddFromFile build "test.glade"
mainWindow <- builderGetObject build castToWindow "mainWindow"
mainWindow `onDestroy` mainQuit
mQuit <- builderGetObject build castToButton "quit"
mQuit `onClicked` mainQuit
entry <- builderGetObject build castToEntry "entry"
mUpdate <- builderGetObject build castToButton "update"
mUpdate `onClicked` do
txt <- entryGetText entry
runState (addToList txt) []
return ()
widgetShowAll mainWindow
mainGUI
-- // --
addToList :: String -> State [String] ()
addToList ent = get >>= \x -> put $ x ++ [ent]
Anyway I think I should be using StateT instead of State but it is a complete mess in my head (have read so many tutos...). Even if it worked, it would not be good since I give an initial state of [] at each loop. The question is how do I write the function addToList so that each time the update button is pressed the user input is added to some state (a list of previous input)?
First of all, State
is already StateT
type State s = StateT s Identity
Maybe you need to use StateT 1 level up, something like this:
runStateT $
put []
lift $ mUpdate `onClicked` do
txt <- lift $ entryGetText entry
listWas <- get
put $ txt : listWas --in reverse order
return ()