haskell - 我的reactive-banana "sum event"有什么问题吗?

标签 haskell reactive-banana

我正在学习reactive-banana并打算在服务器端应用程序中使用它。我有一些 RxJ 背景,所以我习惯将事件与不同的组合器组合在一起。所以我从简单的事件组合器示例开始。我尝试制作一个简单的响应式(Reactive)香蕉示例,它将两个整数事件组合成一个总和事件。我知道,为了能够组合来自不同事件的值,我必须首先将它们放入行为中,然后进行组合,最后将其放入一个新事件中。我就是这样做的:

-- Behaviors from Events e1, e2
let b1 = stepper 0 e1 :: Behavior Int
let b2 = stepper 0 e2 :: Behavior Int

-- Sum Behavior
let sumB = (+) <$> b1 <*> b2
-- Back to Event
let sumE = sumB <@ (e1 `union` e2)

完整的可运行示例可以在 Gist 1594917 中找到.

这里的问题是,虽然当事件(e1、e2)之一出现新值时正确触发 sumE 事件,但它包含一个过时的值。这显然是由于步进器的工作方式造成的(行为值在事件发生“稍微”后发生变化)。我尝试用 Discrete 替换 Behaviour,结果相同。

是否有一种简单的方法可以使此类事件组合器正常工作?

最佳答案

您的诊断完全正确。这里有两个选项:您可以通过更改从离散返回事件,或者您可以创建累积事件。

从离散中恢复可能更简单(也是我推荐的)。就这么做

-- Discretes from Events e1, e2
let d1 = stepperD 0 e1 :: Discrete Int
let d2 = stepperD 0 e2 :: Discrete Int

-- Sum Discrete
let sumD = (+) <$> d1 <*> d2
-- Back to Event
let sumE = changes sumD

现在,当 e1e2 更改时,sumE 将始终更新。

替代方案仅使用事件,将传入事件转换为累积函数。听起来很复杂,但是代码相当简单。

--convert each input into an accumulating tuple
let e1' = (\l (_,r) -> (l,r)) <$> e1
let e2' = (\r (l,_) -> (l,r)) <$> e2

let sumE = uncurry (+) <$> accumE (0,0) (e1' `union` e2')

关于haskell - 我的reactive-banana "sum event"有什么问题吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8826970/

相关文章:

haskell - 使用 cabal 编译但不运行测试套件?

haskell - react 香蕉:如何创建一个 AddHandler?

haskell - react 香蕉 1.0 monadic API : How to define recursive behaviors now?

scala - Scala 中涉及函数依赖的泛型编程和烂香蕉

haskell - 从任意未知 Nats 中提取值

haskell - 在重新启动内执行 MonadIO 操作

haskell - react 香蕉可以处理网络中的循环吗?

haskell - 选择哪种 FRP 包?

haskell - 如果两个模块同名怎么办?

haskell - 将窗口移动到另一台显示器时如何使窗口保持焦点?