我想为我的项目(一个GDB/MI前端)使用 FRP(即反应香蕉 0.6.0.0)。但是我在声明事件网络时遇到了麻烦。
有来自 GUI 的命令,有来自 GDB 的停止事件。两者都需要处理,处理它们取决于系统的状态。
我目前的方法看起来像这样(我认为这是显示问题所需的最低复杂性):
data Command = CommandA | CommandB
data Stopped = ReasonA | ReasonB
data State = State {stateExec :: Exec, stateFoo :: Int}
data StateExec = Running | Stopped
create_network :: NetworkDescription t (Command -> IO ())
create_network = do
(eCommand, fCommand) <- newEvent
(eStopped, fStopped) <- newEvent
(eStateUpdate, fStateUpdate) <- newEvent
gdb <- liftIO $ gdb_init fStopped
let
eState = accumE initialState eStateUpdate
bState = stepper initialState eState
reactimate $ (handleCommand gdb fStateUpdate <$> bState) <@> eCommand
reactimate $ (handleStopped gdb fStateUpdate <$> bState) <@> eStopped
return fCommand
handleCommand
并handelStopped
根据当前状态对命令和停止事件做出反应。可能的反应是调用(同步)GDB I/O 函数和触发状态更新事件。例如:
handleCommand :: GDB -> ((State -> State) -> IO ()) -> State -> Command -> IO ()
handleCommand gdb fStateUpdate state CommandA = case stateExec state of
Running -> do
gdb_interrupt gdb
fStateUpdate f
where f state' = state' {stateFoo = 23}
问题是,当f
由 评估时accumE
,state'
有时与 不同state
。
我不是 100% 确定为什么会发生这种情况,因为我不完全理解时间和同时性的语义以及反应香蕉中“反应”的顺序。但我猜想,由触发的状态更新函数可能会在改变状态handleStopped
之前被评估。f
无论如何,这个事件网络会导致不一致的状态,因为对f
“当前”状态的假设有时是错误的。
我已经尝试解决这个问题一个多星期了,但我就是想不通。任何帮助深表感谢。