2012-08-17 51 views
9

試圖學習使用Gtk2Hs編寫應用程序我在解決事件驅動的Gtk2HS和我的模型的持久狀態之間的差距時遇到了困難。因此,爲了簡化,可以說,我有這個簡單的應用如何處理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 

和我的應用程序的狀態是多少次的按鈕被按下。看到其他職位,如this,他們依賴MVars或IORefs,這對我來說似乎並不令人滿意,因爲將來也許我會重構代碼,以便國家依靠自己的上下文。

我認爲,解決方案應使用階躍函數一樣使用狀態單子:

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

,但我不知道的含義,如何做到這一點在上面的代碼或即使單子是我的問題的正確解決方案。

回答

6

有兩種基本方法:

  1. 使用某種類型的指針。這是您的IORefMVar方法。如果你喜歡,你可以隱藏這個MonadState樣接口後面:

    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. 拉一個「inversion of control」式的把戲。編寫一個打印數字的回調函數,然後用一個新的回調函數代替它自己,打印一個更高的數字。

如果試圖直接使用StateStateT,你就要有一個壞的時間。

+0

非常感謝,真是讓人大開眼界! – fotNelton 2014-10-09 21:59:48

相關問題