2012-08-17 1 views
9

Tenter d'apprendre à écrire des applications avec Gtk2Hs Je rencontre des difficultés pour combler le fossé entre Gtk2HS piloté par les événements et l'état persistant de mon modèle. Donc, pour simplifier, disons que j'ai cette application simpleComment gérer l'état de l'application dans Gtk2Hs

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 

et l'état de ma demande est combien de fois le bouton a été pressé. En voyant d'autres posts comme this ils s'appuient sur MVars ou IORefs qui ne me semblent pas satisfaisants, car dans le futur peut-être je voudrai refactoriser le code afin que l'état vive sur son propre contexte.

Je pense que la solution devrait utiliser la monade d'État en utilisant une fonction étape comme:

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

mais je ne suis pas sûr des conséquences, comment faire dans le code ci-dessus ou même si ce monade est la bonne solution à mon problème.

Répondre

6

Il y a fondamentalement deux approches:

  1. Utilisez un pointeur quelconque. C'est votre approche IORef ou MVar. Vous pouvez cacher derrière une MonadState l'interface -comme si vous le souhaitez:

    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. Tirez un truc de style "inversion of control". Écrire un rappel qui imprime un nombre, puis se remplace par un nouveau rappel qui imprime un nombre plus élevé.

Si vous essayez d'utiliser State ou StateT directement, vous allez avoir un mauvais moment.

+0

Merci beaucoup, ce fut vraiment une révélation! – fotNelton

Questions connexes