Search code examples
haskellfrp

How does Reactive's Monad instance handle simultaneous events?


In Push-Pull Functional Reactive Programming by Conal Elliot, Reactives are given a Monad instance in section 7.1.3. What happens if both the inner and outer reactive fire that the same time for join?

never :: Event a
MkFuture :: Time -> a -> Future a
pure :: a -> Future a -- at time zero
MkReactive :: a -> Event a -> Reactive a
MkEvent :: Future (Reactive a) -> Event a

join (MkReactive (MkReactive "foo" never) (MkEvent (pure (MkReactive "bar" never)))

Should "foo" be ignored or included in the result on the join?


Solution

  • Here is the (slightly paraphrased) join definition from section 7.1.3:

    -- urr is the outer Reactive; ur is the inner one.
    joinR :: Reactive (Reactive a) -> Reactive a
    joinR ((a `Stepper` Ev ur) `Stepper` Ev urr) = a `Stepper` Ev u
        where
        u = ((`switcher` Ev urr) <$> ur) <> (join <$> urr)
    

    The Monoid instance being used in the definition of u is the one for Futures, defined in section 4.5, which in case of simultaneous firings picks the left one. That being so, the inner firing is not discarded if there is a simultaneous firing in join. For the specific example in your question, sampling at time zero should still give out "foo". (I believe the monad law join . fmap return = id would be violated if that wasn't the case)