活性香蕉:状态monad与否?

时间:2015-09-01 16:03:07

标签: haskell reactive-banana

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

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

  2. 如果状态依赖于外部“事件”,考虑到IORef,不仅与GUI相关会更好吗?

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

1 个答案:

答案 0 :(得分:4)

  

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

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

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

要执行的操作属于IO ()类型。虽然可以使用runStateT使用StateT s IO运行reactimate计算,但计算将是自包含的,并且您不会使用它可用的状态通过别处。使用Event通过reactive-banana FRP接口更新Behavior时不会出现此问题:Behavior仍保留在那里,直到您需要再次使用它们为止。

  

如果州取决于外部"事件"考虑到IORef,不仅与GUI相关会更好吗?

不一定。在许多情况下,您可以使用Reactive.Banana.Frameworks中的工具(例如fromAddHandlernewEvent)来创建在发生外部I / O操作时触发的Event。这样,您就可以将此类操作集成到您的事件网络中。一个典型的例子是a timer:reactive-banana没有内置的时间概念,但你可以引入一个通过定期发生的I / O操作触发的tick事件。

那就是说,在某些情况下你可能仍然想要使用......

  • ... IORef s(或其他类型的可变变量,例如MVar s),如果您必须使用具有接口的库,无论出于何种原因,该接口会限制您使用Behaviorreactimate自由地对事件做出反应的能力。不久前有a very nice question about such a scenario involving hArduino。这两个答案显示出不同的,但在精神上相似的方式,在不利的情况下建立有用的事件网络。

  • ... StateT如果你有一些自包含的有状态算法,并且其结果不会在你的事件网络的其他地方使用,那么你可以用{{{}运行它1}}并将其粘贴在runStateT电话中。愚蠢的例子:reactimate中的IO ()行动沿着以下几行:

    reactimate