Reactive Banana的mapAccum功能如何运作?

Joh*_*ler 6 haskell reactive-banana

我已经在Stack Overflow上查看了一些问题的答案,试图在使用Reactive Banana库时找到我的问题的解决方案.所有答案都使用了一些我不太了解的'mapAccum'的魔法.查看API文档,我发现的是"高效组合accumE和" accumB.这不是很有帮助.

似乎这个函数可以用来比较Behavior两个连续事件时a的值,这是我想要做的.但我不清楚如何做到这一点.

mapAccum工作究竟如何?

And*_*ewC 4

请注意

mapAccum :: acc -> Event t (acc -> (x, acc)) -> (Event t x, Behavior t acc)
Run Code Online (Sandbox Code Playgroud)

因此,它需要一个初始值:: acc来累积,并且需要一个事件来生成一个函数,该函数更新该累积值,同时产生一个输出值::x。(通常,您可以通过部分应用某些函数来创建这样的事件<$>。)因此,您会得到一个新的事件,x每当您的值出现时就会触发该事件,并且一个行为包含您当前的累积值。

mapAccum如果您有一个事件并且想要进行相关的行为和事件,请使用。

例如,在其他问题的问题域中,假设您有一个eTime :: Event t Int不规则触发的事件,并且您想要计算eDeltaTime :: Event t Int差异和bTimeAgain :: Behaviour t Int 当前使用的时间:

type Time = Int
type DeltaTime = Time 

getDelta :: Time -> Time -> (DeltaTime,Time)
getDelta new old = (new-old,new)
Run Code Online (Sandbox Code Playgroud)

我可以这样写,getDelta new = \old -> (new-old,new)以使下一步更清晰:

deltaMaker :: Event t (Time -> (DeltaTime,Time))
deltaMaker = getDelta <$> eTime

(eDeltaT,bTimeAgain) = mapAccum 0 $ deltaMaker
Run Code Online (Sandbox Code Playgroud)

在这种情况下,bTimeAgain将是与 中的事件具有相同值的行为eTime。发生这种情况是因为我的getDelta函数new直接通过原样的 fromeTimeacc值。(如果我想要bTimeAgain单独使用,我会使用stepper :: a -> Event t a -> Behaviour t a。)如果我不需要bTimeAgain,我可以只写(eDeltaT,_) = mapAccum 0 $ deltaMaker