我有一个基于 Reactive Banana 的界面 (WX)。 现在我对如何真正管理状态有不同的问题:
我应该将状态视为我在代码中定义的
行为
吗?如果状态也依赖于外部“事件”,那么不仅仅与 GUI 相关,考虑 IORef 会更好吗?
或者我可以使用 State Monad 吗?到目前为止我看到的所有例子都是在 IO 环境中定义网络的。对堆栈
State Monad
有任何意义吗?与时刻
?
最佳答案
Should I consider the state as the Behaviors that I define in the code?
对于大多数场景,您确实需要使用Behavior
来表示状态。在 GUI 应用程序中,您经常需要更新状态以响应界面事件。此外,最重要的是,状态必须在事件发生之间保持存在,而 State
不允许这样做。更具体地说,对事件发生使用react而不是更新 Behavior
的标准方法是通过 reactimate
函数:
reactimate :: Frameworks t => Event t (IO ()) -> Moment t ()
要执行的操作的类型为IO ()
。虽然可以使用 runStateT
来使用 reactimate
运行 StateT s IO
计算,但该计算将是独立的,并且您不会它所使用的状态不能传递到其他地方。当使用Event
通过reactive-banana FRP接口(interface)更新Behavior
时,不会出现这个问题:Behavior
会保留在那里,直到您需要为止再次使用它们。
If the state depends on external "events" too, not only related to the GUI would be better considering IORef?
不一定。在许多情况下,您可以使用 Reactive.Banana.Frameworks
中的工具。例如 fromAddHandler
和 newEvent
来创建在外部 I/O 操作发生时触发的 Event
。这样您就可以将此类操作集成到您的事件网络中。一个典型的例子是 a timer :reactive-banana 没有内置的时间概念,但您可以引入通过定期发生的 I/O 操作触发的刻度事件。
也就是说,在某些情况下您可能仍然想使用...
...
IORef
(或其他类型的可变变量,例如MVar
),如果您必须使用具有以下接口(interface)的库:无论出于何种原因,都会限制您使用行为和重新响应来自由响应事件的能力。前段时间有a very nice question about such a scenario involvinghArduino
。这两个答案展示了在不利情况下建立有用的事件网络的不同但本质上相似的方法。...
StateT
如果您有一些独立的有状态算法,并且其结果不会在事件网络中的其他地方使用,以便您可以使用runStateT
并将其放入reactimate
调用中。愚蠢的示例:reactimate
中的IO ()
操作如下:displayMessageBox . show =<< evalStateT someStateComputation initialState
关于haskell - react 香蕉 : State monad or not?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32336189/