2012-08-17 24 views
9

Tratando de aprender a escribir aplicaciones con Gtk2Hs Tengo dificultades para cerrar la brecha entre el evento guiado Gtk2HS y el estado persistente de mi modelo. Así que para simplificar, digamos que tengo esta sencilla aplicaciónCómo lidiar con el estado de la aplicación en 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 

y el estado de mi solicitud es el número de veces que el botón ha sido presionado. Al ver otras publicaciones como this, confían en MVars o IORefs que no me parecen satisfactorias, porque es posible que en el futuro desee refabricar el código para que el estado viva en su propio contexto.

creo que la solución debe utilizar la mónada estado usando una función de paso como:

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

pero no estoy seguro acerca de las implicaciones, cómo hacerlo en el código anterior, o incluso si esa mónada es la solución correcta para mi problema

Respuesta

6

Hay básicamente dos enfoques:

  1. utilizar un puntero de algún tipo. Este es su enfoque IORef o MVar. Puede ocultar esta detrás de una interfaz -como MonadState si te gusta:

    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. tirar de un "inversion of control" truco estilo. Escriba una devolución de llamada que imprima un número, luego se reemplaza con una nueva devolución de llamada que imprime un número más alto.

Si intenta utilizar State o StateT directamente, vas a tener un mal momento.

+0

Muchas gracias, ¡realmente fue una revelación! – fotNelton

Cuestiones relacionadas