正如 J. Abrahamson 在评论中指出的那样,aBehavior
随时间连续变化,因此标记为 a 变化的离散事件Behavior
没有得到很好的定义。这里有一些替代方案。
按事件改变行为
如果您正在使用响应式包并且正在考虑Behavior
基于 s 更改 s Event
,那么switcher
具有正确的类型:
switcher :: Behavior a -> Event (Behavior a) -> Behavior a
通过重置累积事件
正如您在评论中提到的,如果您想将事件上的累加器重置为x
,只需将const x
事件放入流中即可。这个例子使用了响应式包。
accumBReset :: a -> Event a -> Event (a -> a) -> Behavior a
accumBReset initial resets changes =
accumB initial allChanges
where
allChanges = (fmap const resets) `mappend` changes
反应性
在Push-pull Functional Reactive Programming中,Conal Elliott 描述了该Reactive
类型,类似于Behavior
仅在离散时刻发生变化的 a。
data Reactive a = a `Stepper` Event a
newtype Event a = Ev (Future (Reactive a))
Reactive
可以通过解构它并取构造函数的右侧(即下一个更改其值的事件)将其转换为标记其更改的事件流
changes :: Reactive a -> Event a
changes (_ `Stepper` nextChange) = nextChange
或者,我们可以获取 Reactive 的所有值,包括它现在的样子以及它未来的所有变化
values :: Reactive a -> Event a
values = Ev . pure
Reactive
值在FRP.Reactive.Reactive
反应包中。
从较低级别的行为中获取更改
在某些 FRP 库中,您可以在较低级别执行更多操作。在反应香蕉changes
中,您可以Behavior
在制作自己的Framework
. 这是 Reactive.Banana.Framework
's的类型changes
changes :: Frameworks t => Behavior t a -> Moment t (Event t (Future a))
文档警告说这并没有真正的意义:
输出,观察a何时Behavior
变化。
严格来说,aBehavior
表示一个随时间连续变化的值
,因此没有明确定义的事件来指示行为何时发生变化。
尽管如此,出于效率的原因,该库提供了一种在行为是阶跃函数时观察变化的方法,例如由stepper
. 没有正式的保证,但想法是
changes (stepper x e) = return (calm e)
注意:在事件处理完成之前,事件的值将不可用。它只能在 的上下文中使用reactimate'
。