Closed pyrtsa closed 9 years ago
You may be right. I think it may be possible to force the person always to deal with simultaneity by making only mergeWith available, not merge. I really haven't thought this through.
P.S. I'm not sure how it works right now, but I'd also define sync such that no changes caused by the transaction itself are observable within the transaction.
It does work that way.
I strongly recommend reopening this issue. Life is just too complicated with this design where Stream
s can have multiple firings per transaction:
type S a = [(T, a)] -- for non-decreasing T values
type C a = (a, [(T, a)]) -- for increasing T values
Why not make them both require increasing T values?
Additionally, at least accum
and collectE
seem to be broken in the Haskell implementation. They both ignore all but the last firing per transaction.
In reactive-banana
, I have also used the "multiple occurrences per Event
" model, but I now intend to switch to the proposed "one occurrence per Event
" model as well. It forces the programmer to think about simultaneous occurrences explicitly, which I think is a good thing.
All right - I'm persuaded. Let's do it. Now's the time to do it - before I've finished the book. Any counter-arguments?
The only counterargument I can think of is that we lose the completely general instance Monoid (Event a)
, but I think that's a fair price to pay.
Yeah, already mentioned in my first comment. Fortunately, we can still define
instance Monoid a => Monoid (Event a)
or theoretically even
instance Semigroup a => Monoid (Event a)
94d26530c44ef98bce27a78fa1074486a04dcaf1
commit 94d26530c44ef98bce27a78fa1074486a04dcaf1
Author: Stephen Blackheath <docks.cattlemen.stephen@blacksapphire.com>
Date: Fri Jul 24 10:41:10 2015 +1200
Issue #39: Why support many firings of one Event in a transaction?
With this change, now we don't in the denotational semantics and in the Java
version of Sodium. Other versions will follow as they get revamped to be in
line with the Java version.
I'm not sure if the idea of the same
Event
firing many times "simultaneously" has that much real use. Doesn't it make the model harder to reason about? If there's anEvent
that could yield many values at once, why not reflect that in the type signature, e.g.Event [a]
? (Omitting ther
type parameter here for simplification.)If the semantics of
Event
was simplified to exclude multiple simultaneous firings…newEvent
, in cooperation withsync
, should take care of discarding subsequent actions within the same transaction. Doing so could e.g. emit a warning while debugging, or even just crash the program.merge
andcoalesce
would no longer be needed.Event
s,mergeWith
would work just fine, and the functionality ofmerge
could be replaced (in user code) with alternatives like:Event a
would no longer be aMonoid
but we could still have the followingMonoid
instance:P.S. I'm not sure how it works right now, but I'd also define
sync
such that no changes caused by the transaction itself are observable within the transaction. That has to do with the semantics oflisten
andexecute
as well. But maybe that's a topic worth another discussion (was thinking about this some time ago, but I'm forgetting the details right now).