Question

In reactive-banana I've got an event stream that produces a series of numbers, some of which repeat several times in a row (I'm not concerned with all duplicates, just sequential duplicates). How can I modify that event stream to contain only non-sequential duplicates?

I tried using changes to convert it to a behavior thinking the behavior would only "change" when the event was a new number but instead the behavior triggers a change event every time a new input event is received.

Was it helpful?

Solution

Note that the changes function should only be used for binding to GUI toolkits and thelike, it should not be used for regular programming with events and behaviors.

A function that supresses duplicate event occurrences can be expressed in terms of the mapAccum and filterJust combinators as follows

skipEqual :: Eq a => Event t a -> Event t a
skipEqual = filterJust . fst . mapAccum Nothing . fmap f
    where
    f y (Just x) = if x == y then (Nothing,Just x) else (Just y,Just y)
    f y Nothing  = (Just y, Just y)

test = interpretModel skipEqual $ map (:[]) [1 :: Int,1,2,3,3,2]

Running test gives

*Main> test
[[1],[],[2],[3],[],[2]]

as desired.

In other words, you can simply imagine Event as a list of occurrences and then apply your beloved "list" combinators to that.

OTHER TIPS

Well, changes doesn't turn anything into a Behavior; it just lets you observe the changes of a Behavior in NetworkDescription, so that you can glue it to external frameworks. The behaviour of changes is described as changes (stepper x e)return (calm e), so round-tripping an event through stepper and changes will have no effect other than calm (which simply discards all simultaneous occurrences but the first).

It's useful to have a combinator to discard occurrences that don't change the value, and I think some other FRP frameworks have one built in. But you can write your own pretty easily, as Heinrich's answer shows.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top