如何在反应香蕉中处理多个窗口和单个数据结构

时间:2011-10-28 10:16:22

标签: haskell reactive-programming reactive-banana

我想知道如何设计反应性香蕉来处理以下情况:

假设我有一个中央数据结构。用户可以自由地打开和关闭显示数据的任意数量的不同类型的窗口,并允许用户修改它。

因此,鉴于其性质,我认为只是尝试创建一个大型网络将会运作良好。这是某个东西,每个窗口都有一个网络,并以某种方式连接它们?

在这样的其他情况下,我把数据结构放在每个人发送更新的单个频道后面。然后数据结构将“发布”窗口全部“收听”的更新(火灾事件)。

2 个答案:

答案 0 :(得分:3)

我的一个项目中存在一个相关的问题,它使用类似于MVC架构的东西。中央数据结构引用为

-- the data is a tree, and it's kept as a zipper to the current node
Discrete MyDataZip

以下是我的控制器声明的精简版本:

data Controller st = Controller {
  dState      :: Discrete st
 ,eUpdateZip  :: Event (MyDataZip -> MyDataZip)
 ,eResponse   :: Event (IO ())
 ,bDiagChange :: Behavior (Diagram Cairo R2 -> Diagram Cairo R2)
 }

构造时,大多数控制器都会引用dZip :: Discrete MyDataZip,但无法直接修改它。控制器指定更新的唯一方法是通过Controller数据结构中的eUpdateZip流。

将多个控制器组合成一个图形,它只是放置在存在类型包装器data EControl = forall st. EControl (Controller st)中的控制器列表。我只是mconcat所有单个eUpdateZip参数,以获得用于创建Event (MyDataZip -> MyDataZip)的{​​{1}}的单个流。整个过程是有效的,因为创建新的控制器是纯粹的,所以它可以在相同的let-binding中完成,允许递归引用。

Discrete MyDataZip流中打开新窗口和其他IO任务,类似eResponse d,然后传递给mconcat

您可以查看darcs repo以获取更多详细信息,查看“src / Jaek / UI / Controllers /”和“src / Jaek / UI / ControlGraph.hs”。

编辑:核心问题是,一个大型网络对开发商的POV来说相当笨拙。您可以通过细分网络来降低复杂性,这是一个很好的解决方案。在我的设计中,我通过使反应参与者符合特定的控制器模型,并为这些模型创建明确定义的方法来为网络引入了大量结构。由于我的控制器是持久性的,所有这些都是静态设置的,但它可以动态完成,在这种情况下,我可能在一个线程中运行控制器管理器,并且生成新控制器的操作(例如打开一个新窗口)将发送一个向线程发送消息以创建新控制器。

答案 1 :(得分:1)

目前,在编译后,无法向事件网络添加或删除外部事件(从reactive-banana版本0.4.3开始)。换句话说,无法在单个事件网络中描述您的任务。但是,您可以使用外部事件或多个事件网络,从而产生如下解决方案:

  • 将动态窗口集合映射到一组静态事件源(又名AddHandler件事物)。
  • 或者每个窗口使用一个事件网络,并通过外部事件源进行通信。
  • 每次添加或删除新窗口时重新编译单个事件网络。不幸的是,内部状态将会丢失,因此您必须将其显式化并从外部捕获它(例如在IORef中)。 (这可能是最不令人满意的解决方案。)