假设我有一个活动trigger当被解雇时我想做两件事。首先,我希望它更新一些的值behavior。其次,如果满足其他条件,我希望它触发另一个事件send_off与updated行为的价值。以代码形式表达,假设我有
trigger :: Event b
trigger = ...
updateFromTrigger :: b -> (a -> a)
updateFromTrigger = ...
conditionFromTrigger :: b -> Bool
conditionFromTrigger = ...
behavior :: Behavior a
behavior = accumB initial_value (updateFromTrigger <$> trigger)
send_off :: Event a
send_off = ?????? (filterE conditionFromTrigger trigger)
那么问题是:我该在 ?????? 中放入什么?以便send_off发送最新值behavior,我的意思是包含更新的值trigger这只是应用于它。
不幸的是,如果我理解正确的话,Behavior 的语义是这样的,更新后的值不能立即提供给我,所以我在这里唯一的选择本质上是复制工作并重新计算行为的更新值,以便我可以立即使用它在另一个事件中,即填写 ??????与类似的东西
send_off =
flip updateFromTrigger
<$>
behavior
<@>
filterE conditionFromTrigger trigger
现在,我有一种感觉can通过使用离散而不是行为,使行为中的更新信息立即可供我使用,但这实际上相当于给我一个与原始事件同时触发并具有更新值的事件,除非我错过了一些反应式香蕉并没有给我一种只有当另外两个事件同时触发时才触发事件的方法;也就是说,它提供事件的并集,但不提供交集。
所以我有两个问题。首先,我对这种情况的理解是否正确,特别是我的结论是否正确:我的上述解决方案是解决该问题的唯一方法?其次,纯粹出于好奇,开发者对于如何处理事件的交叉点有什么想法或计划吗?
很好的问题!
不幸的是,我认为有根本问题这里没有简单的解决方案。问题如下:您想要最近的累计值,但是trigger
可能含有同时地正在发生的事件(仍然是有序的)。然后,
哪个同时累加器更新将是最新的?
要点是更新在它们所属的事件流中排序,但与其他事件流无关。这里使用的FRP语义不再知道哪个同时更新到behavior
对应于同时进行的send_off
事件。特别是,这表明您建议的实施send_off
可能是不正确的;当它不起作用时trigger
包含同时发生的事件,因为行为可能会更新多次,但您只重新计算更新一次。
考虑到这一点,我可以想到解决该问题的几种方法:
-
Use mapAccum http://hackage.haskell.org/packages/archive/reactive-banana/0.4.3.0/doc/html/Reactive-Banana-Model.html#v%3amapAccum使用新更新的累加器值注释每个触发事件。
(trigger', behavior) = mapAccum initial_value $ f <$> trigger
where
f x acc = (x, updateFromTrigger acc)
send_off = fmap snd . filterE (conditionFromTrigger . fst) $ trigger'
我认为这个解决方案在模块化方面有点缺乏,但根据上面的讨论,这可能很难避免。
-
重新塑造一切Discrete
.
我在这里没有任何具体的建议,但可能是你的send_off
事件感觉更像是值的更新,而不是真正的事件。在这种情况下,可能值得将一切都考虑在内Discrete
, whose Applicative
当同时发生事件时,实例会做“正确的事情”。
本着类似的精神,我经常使用changes . accumD
代替accumE
因为感觉更自然。
-
下一个版本的reactive-banana(> 0.4.3)可能会包含以下功能
collect :: Event a -> Event [a]
spread :: Event [a] -> Event a
分别具体化。反映同时发生的事件。我需要他们来优化Discrete
无论如何都要输入,但它们可能对于当前问题也很有用。
特别是,它们将允许您这样定义事件的交集:
intersect :: Event a -> Event b -> Event (a,b)
intersect e1 e2
= spread . fmap f . collect
$ (Left <$> e1) `union` (Right <$> e2)
where
f xs = zipWith (\(Left x) (Right y) -> (x,y)) left right
where (left, right) = span isLeft xs
然而,根据上面的讨论,这个函数可能没有你想象的那么有用。特别是,它不是唯一的,有很多变体。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)