Notice that
mapAccum :: acc -> Event t (acc -> (x, acc)) -> (Event t x, Behavior t acc)
so it takes an initial value :: acc
to accumulate on, and an Event which produces a function that
updates that accumulated value whilst producing an output value ::x
. (Typically you'd make such an event by partially applying some function via <$>
.)
As a result you get a new Event that fires your x
values whenever they turn up and a Behaviour containing
your current accumulated value.
Use mapAccum
if you have an event and you want to make a related behaviour and event.
For example in your problem domain from your other question, suppose you have an event eTime :: Event t Int
that fired erratically and you wanted to calculate eDeltaTime :: Event t Int
for the differences and bTimeAgain :: Behaviour t Int
for the currently used time:
type Time = Int
type DeltaTime = Time
getDelta :: Time -> Time -> (DeltaTime,Time)
getDelta new old = (new-old,new)
I could have written that getDelta new = \old -> (new-old,new)
to make the next step clearer:
deltaMaker :: Event t (Time -> (DeltaTime,Time))
deltaMaker = getDelta <$> eTime
(eDeltaT,bTimeAgain) = mapAccum 0 $ deltaMaker
In this case, bTimeAgain
would be a behaviour with the same value as the events in eTime
. This happens
because my getDelta
function passes new
straight through unchanged from eTime
to the acc
value.
(If I wanted bTimeAgain
on its own, I would have used stepper :: a -> Event t a -> Behaviour t a
.)
If I don't need bTimeAgain
, I could just write (eDeltaT,_) = mapAccum 0 $ deltaMaker
.
acc
given to the function in the input event was a good place to store history of events. I kept trying to put the value I was trying to find there instead, when that should have gone in thex
part. – Ligurian