Reactive Banana:状态 monad 与否?

Reactive Banana: State monad or not?

我有一个基于 Reactive Banana 的界面 (WX)。 现在我对如何真正管理状态有不同的疑问:

  1. 我应该将状态视为我在代码中定义的 Behavior 吗?

  2. 如果状态也依赖于外部"events",不仅与GUI相关会更好考虑IORef?

  3. 或者我可以使用 State Monad 吗?到目前为止,我看到的所有示例都定义了 IO 环境中的网络。有任何意义堆栈 State Monad 以及如何?用 Moment?

Should I consider the state as the Behaviors that I define in the code?

对于大多数情况,您确实希望使用 Behaviors 作为状态。在 GUI 应用程序中,您通常希望更新状态以响应界面事件。此外,至关重要的是,状态必须在事件发生之间保持存在,而 State 不允许这样做。更具体地说,除了更新 Behavior 之外,对事件发生做出反应的标准方法是通过 reactimate 函数:

reactimate :: Frameworks t => Event t (IO ()) -> Moment t ()

要执行的操作类型为IO ()。虽然可以使用 runStateT 到 运行 一个 StateT s IO 计算使用 reactimate,但计算将是独立的,并且您不会拥有它使用的可用状态传到别处。当使用 Events 通过 reactive-banana FRP 接口更新 Behaviors 时不会出现此问题:Behaviors 保留在那里,直到您需要再次使用它们。

If the state depends on external "events" too, not only related to the GUI would be better considering IORef?

不一定。在许多情况下,您可以使用 Reactive.Banana.Frameworks such as fromAddHandler and newEvent to create Events that are fired when external I/O actions happen. That way you can integrate such actions to your event network. One typical example would be a timer 中的工具:reactive-banana 没有内置的时间概念,但您可以引入一个滴答事件,该事件通过定期发生的 I/O 动作触发.

也就是说,在某些情况下您可能仍想使用...

  • ... IORefs(或其他类型的可变变量,例如 MVars),如果您必须使用带有接口的库,对于无论出于何种原因,都会限制您使用 Behaviors 和 reactimate 对事件自由做出反应的能力。前阵子有。那里的两个答案显示了在不利情况下建立有用事件网络的不同但本质上相似的方法。

  • ... StateT 如果你有一些独立的有状态算法并且其结果不会在你的事件网络的其他地方使用,那么你可以 运行 它与 runStateT 并将其粘贴在 reactimate 调用中。愚蠢的例子:reactimate 中的 IO () 动作沿着这些行:

    displayMessageBox . show =<< evalStateT someStateComputation initialState