【发布时间】:2013-03-02 00:30:02
【问题描述】:
我不确定这种行为是预期的(即我误用了 Reactive.Banana.Switch)还是错误。
假设我有两个类似类型的输入行为,我想根据一个事件在它们之间切换。我写了这个函数:
switchBehaviors ::
Behavior t a -- | Behavior to yield initially and after "True" events
-> Behavior t a -- | Behavior to yield after "False" events
-> Event t Bool -- | Select between behaviors
-> Moment t (Behavior t a)
switchBehaviors t f es = do
t' <- trimB t
f' <- trimB f
return $ switchB t $ (\e -> if e then t' else f') <$> es
这段代码看起来很无害;当嵌入到简单的 GUI 模型中时,它会进行类型检查、编译并给出所需的结果。 (行为的两个文本输入字段,一个发出交替 True 和 False 事件的按钮,以及一个使用 sink 绑定到组合行为的标签。)
但是,在多次触发事件后,很明显某处发生了灾难性泄漏。应用程序开始花费越来越长的时间来对输入行为的变化和新事件做出反应。它也开始吞噬记忆。
这是一个带有 -hC 的堆配置文件: 我反复切换事件;两个最大的峰值可能是事件的第 20 次和第 21 次触发。
使用 trimB 感觉有点像挥手让类型相加;我不知道我是在正确使用它还是以某种方式滥用它。
我的子问题是:
1) 我是在滥用 Reactive.Banana.Switch API,还是这是一个错误?如果我滥用 API,我做错了什么?
2) 我应该在不使用动态事件切换的情况下执行此操作吗?使用 apply 不会给出正确的行为,因为当底层行为发生变化时,结果事件不会触发。如果我打开事件的所有三个输入,我想我可以设置一个折叠,手动累积每个输入事件的最新值。这是正确的做法吗?
【问题讨论】:
-
reactive-banana 0.7 版还没有为动态切换事件实现垃圾收集,所以任何非常动态的东西都可能占用空间。我在做这个工作。 :-)
-
@HeinrichApfelmus 这个错误还存在吗?我今天尝试了一个动态切换实验(在按键上),在 10 到 20 次按键后,我的程序变得无响应,至少有一次它甚至因堆栈溢出而崩溃。
-
@JasonDagit 开发版本修复了一些可能导致问题的额外空间泄漏。但是,我还没有为动态事件切换实现垃圾回收。
标签: haskell frp reactive-banana