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

发布于 2024-12-12 09:28:16 字数 238 浏览 0 评论 0原文

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

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

因此,考虑到这一点的性质,我认为仅仅尝试创建一个大型网络并不会有很好的效果。每个窗口都有一个网络并以某种方式连接起来吗?

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

I'm wondering how reactive-banana was designed to handle the following situation:

Let's say I have a central data structure. The user is able to freely open and close any number of different types of windows that both display the data, and allow the user to modify it.

So, given the nature of this, I don't think just trying to create one big network would work well. Is this something where each window would have a network and somehow they were connected?

In other situations like this, I had put the data structure behind a single channel that everyone sent updates to. And then the data structure would "publish" updates (fire events) that the windows all "listened" to.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

幽梦紫曦~ 2024-12-19 09:28:16

我的一个项目中有一个相关的问题,该项目使用类似于 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(控制器st)。我只是 mconcat 所有单独的 eUpdateZip 参数来获取单个 Event (MyDataZip -> MyDataZip) 流,该流用于创建离散 MyDataZip。整个事情之所以有效,是因为创建新控制器是纯粹的,因此可以在同一个 let 绑定中完成,从而允许递归引用。

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

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

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

I have a related problem in one of my projects, which uses something akin to an MVC architecture. The central data structure is referenced as

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

Here is a stripped-down version of my controller declaration:

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

When constructed, most controllers get a reference to dZip :: Discrete MyDataZip, but have no way to modify it directly. The only way for a controller to specify an update is via the eUpdateZip stream within the Controller data structure.

Multiple controllers are assembled into a graph, which is just a list of Controllers placed in an existential type wrapper data EControl = forall st. EControl (Controller st). I just mconcat all of the individual eUpdateZip parameters to get a single stream of Event (MyDataZip -> MyDataZip) which is used to create the Discrete MyDataZip. The whole thing works because creating new controllers is pure, so it can be done in the same let-binding, allowing the recursive reference.

Opening new windows and other IO tasks are done in the eResponse stream, which is similarly mconcatd and then passed to reactimate.

You can examine the darcs repo for more details, look in "src/Jaek/UI/Controllers/" and "src/Jaek/UI/ControlGraph.hs".

EDIT: The central problem is that one big network is fairly unwieldy from a developer's POV. You can reduce the complexity by segmenting the networks, which is a good solution. In my design, I introduced a lot of structure to the network by making reactive participants conform to a specific controller model, and creating well-defined means for those models to interact. Since my controllers are persistent that's all set up statically, but it could be done dynamically, in which case I'd probably have controller manager running in one thread, and actions which generated new controllers (such as opening a new window) would send a message to the thread to create a new controller.

暮光沉寂 2024-12-19 09:28:16

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

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

At the moment, it is not possible to add or remove external events to an event network after it has been compiled (as of reactive-banana version 0.4.3). In other words, it is not possible to describe your task in a single event network. However, you can make use of external events or multiple event networks, which leads to solutions like the following:

  • Map a dynamic collection of windows to a static set of event sources (aka AddHandler things).
  • Or use one event network per window and make them communicate via external event sources.
  • Or recompile a single event network every time a new window is added or removed. Unfortunately, the internal state will be lost, so you have to make it explicit and capture it externally (for instance in an IORef). (This is probably the least satisfactory solution.)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文