How to create monadic behaviour in reactive-banana

风格不统一 提交于 2019-12-24 12:46:24

问题


Suppose I catch key presses and manipulate a code buffer accordingly:

let
    bCode = accumB emptyCode eModifications
eCodeChanges <- changes bCode

I would like to create another behaviour bEval

bEval = accumB freshEnv (magic eCodeChanges)

which maps any state of code to its evaluation (triggered only when something really changes).

However, evaluation happens in a monad Interpreter (think hint from hackage). Can I actually define such a behaviour bEval? I guess I could just drag Interpreter String as the state in my behaviour, accumulating with currentAccumState >>= eval nextEvent, but where would I runInterpreter to actually force the evaluation?


Edit: Important thing is that the actions are not merely IO () but are supposed to modify some state. Consider for example clearing a buffer/reseting counter/moving around a zipper.

My idea was along the lines:

f :: a -> Maybe (b -> IO b)

mapJustIO :: (a -> Maybe (b -> IO b)) -> Event t a -> Event t (b -> IO b)
mapJustIO f e = filterJust $ f <$> e

accumIO :: a -> Event t (a -> IO a) -> Behaviour t (IO a)
accumIO z e = fold (>>=) (return z) e

I don't see why there could not be something like this. However, I don't see how to get rid of that IO in the behaviour either :).

Why aren't IO occurrences in reactive-banana actually only MonadIO?


回答1:


The short answer is that combinators like accumB and so on can only work with pure functions. They can't work with functions from the IO monad (or another IO-like monad like Interpreter), because there is no way to define the order of actions in any meaningful way.

To work with IO actions, the combinators from Reactive.Banana.Frameworks are appropriate. For instance, you probably want a function like

mapIO' :: (a -> IO b) -> Event a -> MomentIO (Event b)

See a previous answer for more on this.

In the case of the Interpreter monad from hint, I recommend running it in the main thread, forking a separate thread for your FRP logic, and using TVars or TChan for communication between the two. (I like to calls this the forklift pattern). This way, you can access the Interpreter monad from IO.



来源:https://stackoverflow.com/questions/33088279/how-to-create-monadic-behaviour-in-reactive-banana

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!