reactive-banana如何正确地执行IO事件

时间:2015-10-14 12:29:34

标签: reactive-banana

基于我之前的问题,我的设置逐渐完善(How to create monadic behaviour in reactive-banana):

假设存在eKey,按下某个键时会触发一个事件,b类型Buffer,只要在eKey中发生支持的事件,就会对其进行适当修改,并且最后,对某些事件采取IO次行动。这些IO操作取决于b的状态(为简单起见,假设它们将{​​{1}}的当前状态打印到控制台。)

目前,我有这个选择在事件中发生的操作:

b

然后我做:

getKeyAction :: KeyVal -> Maybe (IO Buffer -> IO Buffer)
getKeyAction 65288 = Just . liftM $ backspace
getKeyAction 65293 = Just $ \mb -> do
    b <- mb
    print $ "PRESSED ENTER: " ++ toString b
    return emptyBuffer
getKeyAction 65360 = Just . liftM $ leftMost
getKeyAction 65361 = Just . liftM $ left
...
getKeyAction _     = Nothing
某些let eBufferActions = filterJust $ getKeyAction <$> eKey bBuffer = accumB (return emptyBuffer) eBufferActions -- model `b` eBuffer <- changes bBuffer reactimate' $ fmap displayBuffer <$> eBuffer

它似乎没有按预期工作。 displayBuffer :: IO Buffer -> IO ()的状态似乎每次重新评估每个事件(每次事件发生时有效地运行到目前为止收集的所有bBuffer个动作),这在我回想起来时是有意义的。

我应该如何重构代码才能正确执行此操作? (即IO个动作查看缓冲区的当前状态,除了缓冲区之外什么都没有累积)

如果我可以在适当的IO事件中构建一个值Event的{​​{1}},那么我可以简单地将我的bBuffer行动映射到它和eKey。你怎么看?怎么做? IO会实现我想做的事吗?但是,如果我使用reactimate快照<@以将b映射到其上,我将如何将当前更改推迟到与当前按键相关联的b

1 个答案:

答案 0 :(得分:1)

好的,所以我相信这解决了我的问题,但我不确定这是正确的做法。所以请评论。

  1. 我将那些执行某些非平凡IOreturn除外)
  2. 的行为分解出来
  3. 我将eKey事件过滤为两个:eBuffereConfirm
    1. eBuffer收集所有修改事件(包括在确认时清除缓冲区)
    2. eConfirm收集所有确认事件
  4. 我使用eConfirm标记bBuffer,用于捕获缓冲区的演变
  5. 最后,我reactimate分别为缓冲区的IOchanges
  6. 代码片段:

    getKeyAction :: KeyVal -> Maybe (Buffer -> Buffer)
    getKeyAction 65288 = Just backspace
    -- omit action for ENTER
    ...
    
    
    getConfirm :: KeyVal -> Maybe (Buffer -> Buffer)
    getConfirm 65293 = Just (const mkBuffer) -- Clear buffer on ENTER
    getConfirm _     = Nothing
    

    然后在网络描述中:

    let
        eBuffer  = filterJust $ getKeyAction <$> eKey
        eConfirm = filterJust $ getConfirm   <$> eKey
        bBuffer  = accumB mkBuffer $ unions [ eBuffer, eConfirm ]
        eEval    = bBuffer <@ eConfirm
    
    eBufferChanges <- changes bBuffer
    
    reactimate  $         evalBuffer <$> eEval
    reactimate' $ fmap displayBuffer <$> eBufferChanges
    

    代表evalBuffer :: Buffer -> IO ()displayBuffer :: Buffer -> IO ()