如何在Gtk2Hs中处理应用程序状态 [英] How to deal with application state in Gtk2Hs

查看:194
本文介绍了如何在Gtk2Hs中处理应用程序状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

试图学习用Gtk2Hs编写应用程序我遇到了一些困难,弥补了事件驱动的Gtk2HS和我的模型的持久状态之间的差距。所以为了简化,可以说我有这个简单的应用程序。

  module Main其中

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

main = do
initGUI
window< - windowNew
button< - buttonNew
set button [buttonLabel:=按下我]
containerAdd窗口按钮

- 事件
onDestroy窗口mainQuit
onClicked按钮(putStrLn --- PUT MEANINGFUL CODE HERE ---)

widgetShowAll窗口
mainGUI

我的应用程序的状态是该按钮被按下了多少次。看到其他职位,如,他们依靠MVars或IORefs对我来说似乎并不令人满意,因为将来也许我会重构代码,以便国家能够依靠自己的环境。



我认为解决方案应该使用State monad来使用step函数,如:

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

但我不确定这些影响,怎么办在上面的代码中,或者即使那个monad是我的问题的正确解决方案。

解决方案

基本上有两种方法: p>


  1. 使用某种指针。这是您的 IORef MVar 方法。如果您喜欢,您可以将它隐藏在 MonadState 类界面之后:

      newtype GtkT sma = GtkT {unGtkT :: ReaderT(IORef s)ma}派生(Functor,Applicative,Monad,MonadIO)
    runGtkT = runReaderT。 unGtkT

    实例MonadIO m => MonadState s(GtkT sm)其中
    get = GtkT(ask>> = liftIO。readIORef)
    put s = GtkT(ask> = liftIO。flip writeIORef s)


  2. 拉一个风格的伎俩。快速和肮脏的 - 重新控制的控制.htmlrel =noreferrer>控制的反转风格的伎俩。写一个回调,打印一个数字,然后用一个新的回调代替自己,输出一个更高的数字。

  3. 尝试直接使用 State StateT ,你会有一段糟糕的时间。


    Trying to learn to write applications with Gtk2Hs I'm getting difficulties bridging the gap between the event driven Gtk2HS and the persistent state of my model. So to simplify, lets say that I have this simple application

    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
    

    and the state of my application is how many times the button has been pressed. Seeing other posts like this they rely on MVars or IORefs which do not seem satisfactory to me, because in the future maybe I will want to refactor the code so the state lives on its own context.

    I think that the solution should use the State monad using a step function like:

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

    but I'm not sure about the implications, how to do that in the above code or even if that monad is the right solution to my problem.

    解决方案

    There's basically two approaches:

    1. Use a pointer of some kind. This is your IORef or MVar approach. You can hide this behind a MonadState-like interface if you like:

      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. Pull an "inversion of control" style trick. Write a callback that prints a number, then replaces itself with a new callback that prints a higher number.

    If you try to use State or StateT directly, you're gonna have a bad time.

    这篇关于如何在Gtk2Hs中处理应用程序状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆