2

基于我之前的问题,我逐渐完善了其设置(如何在反应香蕉中创建单子行为):

假设有eKey,每当按下某个键时就会触发一个事件,该事件b的类型Buffer会在 中发生支持的事件时进行适当修改eKey,最后IO对某些事件采取行动。这些IO操作取决于状态b(为简单起见,假设它们将当前状态打印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具有值的值,那么我可以简单地将我的专用动作映射到它和. 你怎么看?怎么做?会实现我想要做的事情吗?但是,在我拍摄with的快照以映射它之后,我将如何将当前更改推迟到与当前按键相关联?bBuffereKeyIOreactimate<@bb<@Buffer -> IO ()

4

1 回答 1

1

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

  1. 我排除了那些做一些不平凡的动作IO(除了return
  2. 我将事件过滤eKey成两个:eBuffereConfirm
    1. eBuffer收集所有修改事件(包括确认时清除缓冲区)
    2. eConfirm收集所有确认事件
  3. eConfirm我用 的值标记bBuffer,捕获缓冲区的演变
  4. 最后,我reactimate将缓冲区的IOchanges

代码片段:

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 ()

于 2015-10-14T14:45:42.573 回答