2015-10-14 33 views
2

基於我剛纔的問題,其設定我逐漸細化(How to create monadic behaviour in reactive-banana):反應香蕉怎麼辦IO事件正確

假設有eKey,一個觸發的事件,只要按下一個鍵,Buffer類型的b這是隻要在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行動看緩衝的當前狀態,那麼除了該緩衝區被累積)


如果我能構建一個Event上適當eKey事件之際承擔bBuffer的價值,那麼我可以簡單地映射我的專用IO動作和reactimate。你怎麼看?怎麼做? <@會實現我想要做的事情嗎?但是,我如何將b<@之間的快照映射到Buffer -> IO()之後,將當前更改推遲到與當前按鍵相關聯的b

回答

1

好的,我相信這解決了我的問題,但我不確定這是否正確。所以請評論。

  1. 我分析出那些做一些不平凡的IO(除return)行動
  2. 我的eKey事件過濾器分爲兩個:eBuffer和​​
    1. eBuffer收集所有修改事件(包括結算確認緩衝區)
    2. ​​收集所有確認事件
  3. 我標籤​​與bBuffer值,其捕獲緩衝器的演變
  4. 最後,我reactimate分開IO和緩衝的changes

的代碼片段:

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

+0

對我很好。第一步是一切的關鍵。這就是說,我對你的命名約定有點困惑。你爲什麼稱它爲「evalBuffer」?據我所知,「緩衝區」是一個不變的值,你可以通過應用純函數'緩衝區 - >緩衝區'來改變它。 –

+0

'evalBuffer'是一個'IO'動作,它獲取'Buffer'的「當前」狀態並對其進行評估(將緩衝區發送給解釋器並將結果輸出到控制檯)。如果你的意思是'eEval',那就是需要評估的事件。我個人並不支持這個命名,這只是我的第一個想法。 – jakubdaniel