QStateMachine框架提供了一种很好的声明方式来定义基于状态事件的应用程序。即然后发生一个事件,它执行一个回调(实际上它会触发一个信号但这还不够)并根据图形执行状态转换。
我对FRP没有任何实际经验,但通过浏览反应性香蕉的例子,我没有发现FRP是否可以解决类似的问题。例如,“两个计数器”示例处理状态为plain if 和 accumB 。
那么有一种干净且声明性的融合FSA和FRP的方法吗?
答案 0 :(得分:1)
请原谅我,如果我错过了关于FSA的观点,但我相信accumB
和朋友可以很好地和声明地捕捉到你的目标。从本质上讲,个别状态是价值,而转变是功能。一个非常简单的例子可能从:
data ToggleState = Off | On deriving (Show)
toggle :: ToggleState -> ToggleState
toggle Off = On
toggle On = Off
emergencyShutdown :: ToggleState -> ToggleState
emergencyShutdown _ = Off
(目前我没有找到好的想法来捕捉QState()
的“开放式枚举”式的schtick,虽然我认为这并不是什么大问题,因为他们偏爱典型的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元素可以通过绑定模块轻松完成(在reactive-banana-wx中查找sink
,或者就此而言,查找threepenny-gui)。等等。