如何在反应香蕉中创建单子行为 [英] How to create monadic behaviour in reactive-banana

查看:129
本文介绍了如何在反应香蕉中创建单子行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我抓住了按键并相应地操作了代码缓冲区:

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

let
    bCode = accumB emptyCode eModifications
eCodeChanges <- changes bCode

我想创建另一个行为bEval

bEval = accumB freshEnv (magic eCodeChanges)

将任何代码状态映射到其评估(仅在真正改变的情况下触发).

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

但是,评估是在monad Interpreter中进行的(从hackage中考虑hint).我真的可以定义这样的行为bEval吗?我想我可以将Interpreter String拖动为行为状态,并累积currentAccumState >>= eval nextEvent,但是我runInterpreter在哪里实际强制评估?

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?

编辑:重要的是,这些动作不仅是IO ()而是应该修改某些状态.例如,考虑清除缓冲区/重置计数器/在拉链中移动.

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.

我的主意是:

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

我不明白为什么不能有这样的东西.但是,我也看不到如何摆脱IO的行为:).

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 :).

为什么IOreactive-banana中实际上不是仅出现在MonadIO中?

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

推荐答案

简而言之,就是像accumB之类的组合器只能与 pure 函数一起使用.它们无法使用IO monad(或其他类似IO的monad,如Interpreter)中的函数,因为无法以任何有意义的方式定义操作顺序.

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.

要使用IO操作,Reactive.Banana.Frameworks中的组合器是合适的.例如,您可能想要一个类似

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.

对于hint中的Interpreter monad,我建议在主线程中运行它,为您的FRP逻辑分叉一个单独的线程,并使用TVar s或TChan进行两者之间的通信. (我将此称为叉车模式).这样,您可以从IO访问Interpreter单子.

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.

这篇关于如何在反应香蕉中创建单子行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆