HeinrichApfelmus/reactive-banana — Issue #25: Proposal: Disallow multiple simultaneous events
Author: HeinrichApfelmus
Created: 2012-01-03 12:25:50+00:00
State: open
Labels: design-discussion

When merging two event stream, what should happen to simultaneous event occurrences? As of reactive-banana version 0.4, they will be kept around and ordered from left to right. Here an example in terms of the model implementation:

union [[1],[2]], [[3],[]] = [[1,3], [2]]

### Proposal
I propose to dispense with these kind of simultaneous event occurrences and change the `Event` data type so that only a single event may happen at each point in time.

The type of `union` will be changed to

union :: Monoid a => Event a -> Event a -> Event a

Instead of appending simultaneous events, the `union` function would merge them into a single event occurrence, using the `mappend` combinator.

### Properties
1. Since `a -> a` is a monoid, this works well in conjunction with the accumulation functions `accumE`, `accumB`. Existing code is essentially unchanged in this regard, except for ordering.

2. Merging events in other cases will be a little less pleasant, we probably need a left-biased union

lunion :: Event a -> Event a -> Event a
x `lunion` y = (filterJust . getFirst) (First x `mappend` First y)

The drawback is that event occurrences may be lost this way.

3. The following two behaviors are now equivalent

initial :: A
update :: A -> A

behavior1 :: Event () -> Behavior A
behavior1 e = accumB initial $ update <$ e
where event = update <$> (b1 <@ e)

behavior2 :: Event () -> Bevahior A
behavior2 e = stepper initial event
where event = accumE initial $ update <$ e

In the presence of simultaneous event occurrences, these two programs are *not* equivalent because the event `e` may contain multiple occurrences.

4. To summarize 2 and 3: the trade-off is that we now have to think about simultaneous events whenever we take the union of two event streams, but we are freed from thinking about them when we take the snapshot of a behavior. Gregory Crosswhite reports that this would probably simplify a program he writes.

5. The problem about optimizing the `Discrete` type (issue #19) disappears.

6. The old semantics can always be obtained as `Event [a]` if desired. In fact, that's how the model implementation defines the current semantics. The `calm` function mentioned in issue #19 becomes straightforward to implement.

### Discuss!

What do you think? How would this change affect your existing code base?