I'm learning reactive-banana and intending to use it in a server-side app. I have some background in RxJs, so I'm used to combining Events with different combinators there. So I started with simple event combinator examples. I tried to make a simple reactive-banana example that would combine two integer events into a sum event. I understand that to be able to combine values from different events, I have to make them into Behaviors first, the do the combination and finally make that into a new event. This is how I did it:
-- Behaviors from Events e1, e2
let b1 = stepper 0 e1 :: Behavior Int
let b2 = stepper 0 e2 :: Behavior Int
-- Sum Behavior
let sumB = (+) <$> b1 <*> b2
-- Back to Event
let sumE = sumB <@ (e1 `union` e2)
Full runnable example can be found in Gist 1594917.
The problem here is that while the sumE event is correctly triggered when a new value appears in one of the events (e1, e2), it contains a stale value. This is apparently due to how stepper works (the value of the behavior changes "slightly after" the event occurrences). I tried replacing Behavior with Discrete, with the same result.
Is there a simple way to make this kind of event combinators work correctly?
Your diagnosis is exactly correct. Here are two options: you can work back to an Event from Discrete via
changes
, or you can create accumulating events.Working back from Discrete is probably simpler (and is what I would recommend). Just do
Now
sumE
will always update whene1
ore2
changes.The alternative uses only Events, by converting incoming events into accumulating functions. It sounds complex, but the code is fairly simple.