Based on my previous question whose setting I refined gradually (How to create monadic behaviour in reactive-banana):
Suppose there is eKey
, an event fired whenever a key is pressed, b
of type Buffer
which is modified appropriately whenever a supported event occurs in eKey
, and finally there are IO
actions to be taken on some of the events. These IO
actions depend on the state of b
(for simplicity assume they print the current state of b
to the console).
Currently, I have this to select the action that happens on an event:
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
and then I do:
let
eBufferActions = filterJust $ getKeyAction <$> eKey
bBuffer = accumB (return emptyBuffer) eBufferActions -- model `b`
eBuffer <- changes bBuffer
reactimate' $ fmap displayBuffer <$> eBuffer
for some displayBuffer :: IO Buffer -> IO ()
.
It does not seem to work as intended. The state of bBuffer
seems to be evaluated on every event anew (effectively running all IO
actions collected thus far every time an event occurs) which makes sense when I think about it in retrospect.
How should I refactor my code to do this correctly? (i.e. IO
actions see current state of the buffer, nothing except the buffer gets accumulated)
If I could construct an Event
that bears value of the bBuffer
on occasion of an appropriate eKey
event, then I could simply map my a dedicated IO
action over it and reactimate
. What do you think? How to do that? Would <@
achieve what I am trying to do? But how would I postpone the current change to b
associated with the current key press after I take snapshot of b
with <@
to map the Buffer -> IO ()
over it?