2012-08-17 15 views
9

Versuchen zu lernen, Anwendungen mit Gtk2Hs zu schreiben Ich bekomme Schwierigkeiten, die Lücke zwischen dem ereignisgesteuerten Gtk2HS und dem anhaltenden Zustand meines Modells zu überbrücken. So vereinfachen, kann sagen, dass ich diese einfache AnwendungWie man mit Anwendungsstatus in Gtk2Hs umgehen kann

module Main where 

import Graphics.UI.Gtk 
import Control.Monad.State 

main = do 
    initGUI 
    window <- windowNew 
    button <- buttonNew 
    set button [buttonLabel := "Press me"] 
    containerAdd window button 

    -- Events 
    onDestroy window mainQuit 
    onClicked button (putStrLn ---PUT MEANINGFUL CODE HERE---) 

    widgetShowAll window 
    mainGUI 

und der Zustand meiner Anwendung ist, wie oft die Taste gedrückt wurde. Wenn sie andere Beiträge wie this sehen, verlassen sie sich auf MVars oder IORefs, die mir nicht befriedigend erscheinen, weil ich in Zukunft vielleicht den Code umgestalten will, damit der Staat von seinem eigenen Kontext lebt.

Ich denke, dass die Lösung den Staat Monade mit einer Sprungfunktion wie verwenden soll:

State $ \s -> ((),s+1) 

aber ich bin mir nicht sicher über die Auswirkungen, wie zu tun, dass in dem obigen Code oder auch wenn das Monade ist die richtige Lösung für mein Problem.

Antwort

6

Es gibt grundsätzlich zwei Ansätze:

  1. einen Zeiger irgendeiner Art verwenden. Dies ist Ihr IORef oder MVar Ansatz. Sie können dies hinter einer MonadState -ähnlichen Schnittstelle verbergen, wenn Sie mögen:

    newtype GtkT s m a = GtkT { unGtkT :: ReaderT (IORef s) m a } deriving (Functor, Applicative, Monad, MonadIO) 
    runGtkT = runReaderT . unGtkT 
    
    instance MonadIO m => MonadState s (GtkT s m) where 
        get = GtkT (ask >>= liftIO . readIORef) 
        put s = GtkT (ask >>= liftIO . flip writeIORef s) 
    
  2. Ziehen Sie einen „inversion of control“ Stil Trick. Schreiben Sie einen Rückruf, der eine Zahl ausgibt, und ersetzt sich dann durch einen neuen Rückruf, der eine höhere Zahl ausgibt.

Wenn Sie versuchen, direkt State oder StateT zu verwenden, du wirst haben eine schlechte Zeit.

+0

Vielen Dank, das war wirklich ein Augenöffner! – fotNelton