Separating State for a Model and GUI IO ( Wx) : Stack or FRP?
For my diagramming tool, I'd like to keep the code of the core model isolated from the GUI.
 In the following example, the "state " is passed around with vDiag , which is a Tvar .  This is a design decision in wx.  Now, For my diagramming tool, I 'd like the core model to be "stored" in a fgl Graph, (with complex types in it), and wx will be given only a view on it;  say in this example, a list of points for read access when painting, and some functions to write when clicking, dragging, etc.. .  I thought first to some Monad stack, but even combining a StateT and the IO from wx does not look trivial , because the io actions are spread all over in the code of the callback (on click , on paint…etc ).  It feels like having IO at the bottom of the stack does not fit well anymore.  
so how to you pass a STate around, or is it not the way to go ? ( I intuition this is a classic. is this how RFP started ? )
 (In the code, which paints red circle when there is a click , the list of points are passed around in a Tvar vDiag . I have tagged "--fgl" where equivalent state accessor would go. and set up a basic fgl test graph accessors to illustrate . I would like to put in a State) (I originally tried to give it a go without FRP - reactive banana, to understand the problem, but I think I may have already hit it ;-)  
module Main where
import Graphics.UI.WX hiding (empty)
import Data.Graph.Inductive
main
  = start ballsFrame 
ballsFrame
  = do 
  vDiag  <- varCreate [] 
  --gDiag  <- initg -- fgl
  frame  <- frame    [text := "Demo"]
  p <- panel frame []
  file   <- menuPane [text := "&File"]
  quit   <- menuQuit file [on command := close frame]
  set frame [text:= "testing", menuBar := [file] ]
  set p [on click := drawBins vDiag p , on paint := paintDiag vDiag ] 
                -- fgl pass the var around
  return ()  
    where
    drawBins  d ppanel pt = 
                do varUpdate d  (pt:) 
                    -- addpoint f g -- fgl : insert a point
                   repaint ppanel
    -- paint the balls
    paintDiag vdiag dc view
      = do  balls <- varGet vdiag  -- getPointsFromGraph 
        -- fgl : change to get the list of points
            set dc [brushColor := red, brushKind := BrushSolid] 
            mapM_ (drawDiag dc)  balls
    drawDiag dc pt
      = circle dc pt 10 []
-- basic fgl test graph accessors  I would like to put in a State and replace vDiag
initg:: Gr Point  String
initg = mkGraph [(1,pt 10 10),(2,pt 30 30)] [(1,2,"truc"), (2,1,"revtruc")]
getPointsFromGraph :: Graph gr => gr b b1 -> [b]
getPointsFromGraph g = map snd $ labNodes g
-- getPointsFromGraph initg = [Point {pointX = 10, pointY = 10},Point {pointX = 30, pointY = 30}]
addpoint :: DynGraph gr => a -> gr a b -> gr a b
addpoint p g = -- add a point p into graph p
               insNode (4,p) g
                        链接地址: http://www.djcxy.com/p/58762.html
                        上一篇: 在功能解释器中序列化正在运行的程序
