gtk - How can I reduce the number of arguments I have to pass around in Haskell? -
i'm getting speed in haskell, trying gui toolgit usable, etc. followed basic tutorial on using glade create simple gui app , i'm trying modularize it. in particular, wanted leverage functions instead of doing in main. first thing did create separate functions accessing buttons , associating code executed when buttons clicked. works fine if @ code below, have carry entire glade xml "variable" around me. realize don't global in haskell seems me there has improve mechanism rather carrying every single variable around in functions. in oo world, xml stuff instance variable in class implicitly available everywhere. what's "right" way in haskell world?
module main (main) import graphics.ui.gtk import graphics.ui.gtk.glade getbutton :: gladexml -> string -> io button getbutton gladexml buttonname = xmlgetwidget gladexml casttobutton buttonname onbuttonclick :: gladexml -> string -> [io a] -> io () onbuttonclick gladexml buttonname codesequence = abutton <- getbutton gladexml buttonname _ <- onclicked abutton $ -- run sequence of operations when user clicks sequence_ codesequence homecoming () loadgladefile :: filepath -> io (maybe gladexml) loadgladefile filename = g <- xmlnew filename homecoming g main :: io () main = _ <- initgui -- setup -- load glade xml file xml <- loadgladefile "tutorial.glade" -- create main window (everything within created too) window <- xmlgetwidget xml casttowindow "window1" -- define when quit _ <- ondestroy window mainquit -- show wondow widgetshowall window -- associate onclick event button onbuttonclick xml "button1" [putstrln "hello, world"] -- off go maingui
this suggestion augustss' comment. thoroughly untested, started:
import control.applicative import control.monad import control.monad.trans import control.monad.trans.reader import graphics.ui.gtk import graphics.ui.gtk.glade getbutton :: string -> readert gladexml io button getbutton buttonname = gladexml <- inquire homecoming . lift $ xmlgetwidget gladexml casttobutton buttonname
to run readert gladexml io
action:
-- well, should utilize `runreadert` directly, @ to the lowest degree -- type signature here instructive. rungladexmlreader :: readert gladexml io -> gladexml -> io rungladexmlreader = runreadert
try reading docs on control.monad.trans.reader
, , monad transformer tutorials.
let me seek again. i'm doing combining 2 ideas can tackle separately, set together:
thereader
monad monad transformers you might start reading these seek understand reader
monad:
reader
("the world of future values") reader monad purpose help reader monad basically, reader
monad constructs values depend on missing, implicit "environment" value. within reader
monad there action called ask :: reader r r
result environment value.
so thought everywhere have gladexml -> something
, can rewrite function monadic action of type reader gladexml something
. example, simplification of illustration above (no monad transformer):
getbutton :: string -> reader gladexml (io button) getbutton buttonname = -- variable gladexml gets value of "implicit" gladexml value gladexml <- inquire -- utilize value argument xmlgetwidget function. homecoming $ xmlgetwidget gladexml casttobutton buttonname
the way utilize reader
runreader :: reader r -> r -> a
function. schematically:
{- note: none of guaranteed compile... -} illustration :: io button illustration = _ <- initgui -- setup xml <- loadgladefile "tutorial.glade" runreader (getbutton "button1") xml
however, since you're using both reader
, io
in here, want create combined monad has "powers" of both. that's monad transformers add together picture. readert gladexml io a
is, conceptually, io
action has access "implicit" gladexml value:
getbutton :: string -> readert gladexml io button getbutton buttonname = gladexml <- inquire -- there 1 catch: utilize io action, have prefix -- `lift` function... button <- lift $ xmlgetwidget gladexml casttobutton buttonname homecoming button -- i've refactored *not* take list of actions. onbuttonclick :: string -> readert gladexml io -> readert gladexml io () onbuttonclick gladexml buttonname action = abutton <- getbutton buttonname xml <- inquire _ <- lift $ onclicked abutton (runreadert action xml) homecoming () -- piece of code illustrates payoff of refactoring. -- note how there no variable beingness passed around xml. -- because i'm making "big" readert action out of little ones, , -- implicitly same `gladexml` value threaded through them. makebutton1 :: readert gladexml io button makebutton1 = button1 <- getbutton "button1" onbuttonclick "button1" $ lift $ putstrln "hello, world" homecoming button1 -- `main` action fetches `gladexml` value , hands off -- actual main logic, `readert` expects `gladexml` main :: io () main = xml <- ... runreadert actualmain xml actualmain :: readert gladexml io () actualmain = ...
haskell gtk glade
No comments:
Post a Comment