我可以想象,对此的整体回答将推动我进入Functional Reactive Programming,但是...忍受着我一段时间。是否可以在GTK和Haskell中为State monad中的数据创建TreeModel?
我也没有这个问题的示例代码。我用我的一些代码在主题附近徘徊,但我一直坚守在它的IO monad中。
想象一下,我有一个应用程序,在这个应用程序中,我将建模一些复杂的状态并将其放入整个应用程序状态monad中。我这样做是因为我想要在核心应用程序和特定用户界面之间有一定程度的分离。
data S = S DataStore EventStream Sockets
type AppState m = StateT S m
(假设数据存储,EventStream和套接字是所有的数据类型基本上做什么,他们听起来像:))
现在,说我想创建GTK(表中的TreeView,但没有子节点)只能查看EventStream。我已经学会了这样做,通过说listStoreNew event_stream >>= treeViewNewWithModel
(见http://markus.alyra.org/?p=1023在那里我非常广泛地谈论这个设置的机制)。
但是,现在我有一个可变副本我的AppState monad中的数据。当应用程序关闭并执行一些将新数据附加到EventStream的操作时,该视图中不会显示该数据。我能想到的唯一方法就是在视图中显示除了对monad所做的更改外,还会发送一条消息,如listStoreInsert my_new_event
。这是可行的,但开始感觉笨拙。
更糟糕的是,这个神话般的树视图是一个管理视图!这是可编辑!管理员说:“哦,那个事件有一些无效的数据,我想改变它!”。现在,我无法更改上面创建的ListStore中的数据。我可以创建回调,使更新没有问题。但我无法想象如何将更新导入Global AppState Monad。
而那些最后几个字显示了问题的核心。如果我有一个全局的AppState Monad,那么更新该monad的任何内容都必须在一行执行中,并且要查看monad的所有内容。 TreeView打破了这一点。当单元格在TreeView monad中编辑时,编辑处理程序完全在IO monad中运行,并且预计不会返回任何内容。最终数据类型为IO()
。即使我有一些漂亮的方式从我的AppState中打开数据,然后执行编辑处理程序,然后将数据重新包装到AppState中,应用程序的其他分支无法看到它。
即使我能想出如何创建自己的完全自定义的ModelView实例,该实例向我的AppState提供只读视图,但我无法想象如何使状态更新可用于其他应用程序。
所以......
它甚至有可能以这种方式来建模GTK /哈斯克尔应用?或者,我是否走上了疯狂之路?
我认为你的例子是非常现实的(即没有人为的)。我完全没有想过使用MVar。这可能是一个相当有趣的解决方案。 – 2012-07-11 15:10:23
我正在用手机写这一切,所以请原谅这些混乱的解释。之前我输入的一个例子更具人为性,涉及回调等不同的线程,但我意识到即使在具有不透明事件处理程序的单个线程上使用事件轮询时也需要解决相同的问题。 – dflemstr 2012-07-11 15:55:35
周末我开始玩这个解决方案。我喜欢。不禁感慨我插入了一个额外的间接层,但我希望能够解决这个问题,因为我在Haskell上做得更好。 – 2012-07-23 21:18:34