1

QStateMachine框架提供了一种很好的声明方式来定义基于有状态事件的应用程序。即,然后发生一个事件,它执行一个回调(实际上它触发一个信号,但这还不够)并根据图表执行状态转换。

我对 FRP 没有任何实际经验,但是通过浏览 reactive-banana 的示例,我没有发现 FRP 是否可以解决类似的问题。例如,“两个计数器”示例通过普通ifaccumB处理状态。

那么有没有一种干净且声明性的方式来融合 FSA 和 FRP?

4

1 回答 1

1

如果我错过了关于 FSA 的要点,请原谅我,但我相信accumB和朋友可以很好地和声明性地捕捉你的目标。本质上,单个状态是值,而转换是函数。一个非常简单的例子可能开始于:

data ToggleState = Off | On deriving (Show)

toggle :: ToggleState -> ToggleState
toggle Off = On
toggle On  = Off

emergencyShutdown :: ToggleState -> ToggleState
emergencyShutdown _ = Off

(现在我没有什么好主意来捕获类似“开放枚举”的 schtick QState(),尽管我认为这并不是什么大不了的事,考虑到典型的 Haskeller 对强类型的偏好。)

然后,我们建立 FRP 网络,将状态捕获为行为(即随时间变化的值)并将转换捕获为事件:

-- Assuming eFlipSwitch and ePushShutdownButton are
-- defined terms of user input; say, through
-- bindings to your favourite UI library.
let
    eToggle :: Event t (ToggleState -> ToggleState)
    eToggle = toggle <$ eFlipSwitch

    eShutdown :: Event t (ToggleState -> ToggleState)
    eShutdown = emergencyShutdown <$ ePushShutdownButton

    -- By defining the behavior, we state once and for all the
    -- temporal evolution of the state in terms of the transitions.
    bState :: Behavior t ToggleState
    bState = accumB Off $ eToggle `union` eShutdown

还有很多其他的可能性。IO回调可以由事件通过reactimate. 如 QStateMachine 文档中所述,可以使用filterE相关的组合器来完成守卫。动画 UI 元素可以很容易地通过绑定模块完成(sink在 reactive-banana-wx 中查找,或者就此而言,在threepenny-gui 中查找)。等等。

于 2013-11-21T21:22:23.220 回答