如何处理reactive-banana中的多个窗口和单个数据结构



我想知道reactive-banana是如何设计来处理以下情况的:

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

所以,考虑到这个的性质,我不认为仅仅试图创建一个大网络会很好。是不是每个窗口都有一个网络,它们以某种方式连接在一起?

在其他类似的情况下,我将数据结构放在每个人发送更新的单个通道后面。然后数据结构将"发布"所有窗口都"收听"的更新(5个事件)。

在我的一个项目中有一个相关的问题,它使用了类似于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的引用,但没有办法直接修改它。控制器指定更新的唯一方法是通过控制器数据结构中的eUpdateZip流。

多个控制器被组装成一个图,这只是一个放在存在类型包装器data EControl = forall st. EControl (Controller st)中的控制器列表。我只是mconcat所有单独的eUpdateZip参数,以获得用于创建Discrete MyDataZipEvent (MyDataZip -> MyDataZip)的单个流。因为创建新控制器是纯粹的,所以它可以在相同的let-binding中完成,允许递归引用。

打开新窗口和其他IO任务在eResponse流中完成,这与 mconcatd相似,然后传递给reactimate

你可以查看darcs的详细信息,查看"src/Jaek/UI/Controllers/"one_answers"src/Jaek/UI/ControlGraph.hs"。

编辑:核心问题是,从开发人员的角度来看,一个大的网络是相当笨拙的。您可以通过对网络进行分段来降低复杂性,这是一个很好的解决方案。在我的设计中,我通过使响应性参与者符合特定的控制器模型,并为这些模型创建良好定义的交互方式,为网络引入了许多结构。由于我的控制器是持久的,这都是静态设置的,但它可以动态完成,在这种情况下,我可能有控制器管理器运行在一个线程中,生成新控制器的动作(如打开一个新窗口)将发送一个消息给线程来创建一个新控制器。

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

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

最新更新