我不确定这种行为是预期的(即我误用了 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
.)
然而,在多次触发该事件后,很明显某处存在灾难性泄漏。应用程序开始花费越来越长的时间来对输入行为的变化和新事件做出反应。它还开始吞噬内存。
Here's a heap profile with -hC:
I'm repeatedly toggling the Event; the two largest spikes are maybe the twentieth and twenty-first firings of the Event.
使用trimB感觉有点像挥手让类型加起来;我不知道我是否正确使用它或以某种方式滥用它。
我的子问题是:
1)我是否滥用了 Reactive.Banana.Switch API,或者这是一个错误?如果我滥用 API,我做错了什么?
2)我应该在不使用动态事件切换的情况下执行此操作吗?使用apply
没有给出正确的行为,因为当底层行为发生变化时,生成的事件不会触发。如果我打开事件的所有三个输入,我想我可以设置一个折叠,手动累积每个输入事件的最新值。这是正确的方法吗?