I have looked at a number answers to questions here on Stack Overflow trying to find a solution to my problem in using the Reactive Banana library. All the answers use some magic using ‘mapAccum’ that I can’t quite understand. Looking at the API documentation all I find is “Efficient combination of accumE and accumB.” which is not very helpful.
It seems that this function can be used to compare the values of a Behavior at the time of two consecutive events which is what I’d like to do. But I not clear how to make that work.
How exactly does mapAccum work?
Notice that
so it takes an initial value
:: accto accumulate on, and an Event which produces a function thatupdates 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
xvalues whenever they turn up and a Behaviour containingyour current accumulated value.
Use
mapAccumif 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 Intthat fired erratically and you wanted to calculateeDeltaTime :: Event t Intfor the differences andbTimeAgain :: Behaviour t Intfor the currently used time:
I could have written that
getDelta new = \old -> (new-old,new)to make the next step clearer:In this case,
bTimeAgainwould be a behaviour with the same value as the events ineTime. This happensbecause my
getDeltafunction passesnewstraight through unchanged fromeTimeto theaccvalue.(If I wanted
bTimeAgainon its own, I would have usedstepper :: a -> Event t a -> Behaviour t a.)If I don’t need
bTimeAgain, I could just write(eDeltaT,_) = mapAccum 0 $ deltaMaker.