Implementing zipE :: Event t a -> Event t b -> Event t (a,b)
Asked Answered
A

1

6

I am new to reactive banana and FRP in general, so apologies if I am missing something obvious.

For my project (a GDB/MI front-end) I am using reactive banana (version 0.6.0.0) for both the GUI and the front-end logic modules. The former works great but for the latter I apparently need additional combinators.

One of them is zipE :: Event t a -> Event t b -> Event t (a, b). Unfortunately, all I could come up with is a solution in the NetworkDescription monad that uses changes and is not generic in the event types:

zipE :: Event t Int -> Event t String -> NetworkDescription t (Event t (Int, String))
zipE ea eb = changes $ (,) <$> stepper 0 ea <*> stepper "" eb

Of course, I am not satisfied with this. Thus I wanted to ask how to implement a generic zipE function without using changes (which is discouraged to use for non-GUI purposes).

Other attempts failed, e.g.

zipE :: Num a => Event t a -> Event t b -> Event t (a,b)
zipE ea eb = apply (stepper (0,) ((,) <$> ea)) eb

results in the first elements of the tuples being shifted by one - I guess due to the "slight delay" introduced by stepper. But I don't see how to obtain a behavior from an event without stepper (or accumB for that matter) and I don't see how to apply a function to an event without a behavior. And overall, I don't see how to provide an initial value to stepper in case of a generic type.

Alsoran answered 31/7, 2012 at 14:37 Comment(3)
ea and eb are not going to fire at the same time. (If you know they're going to fire at the same time because they're both derived from the same underlying event, it's probably best to reprocess that underlying event.) What do you want to happen when one fires and the other doesn't?Linage
Dave, you are right. I need a different design for my event network :-/ Thank you for pointing this out.Alsoran
I indeed required a different event network. Initially, I wanted to zip the two events to feed the tuples into f :: (a,b) -> IO (). What I have now instead is f :: a -> b -> IO () and reactimate $ (f <$> stepper 0 aE) <@> bE.Alsoran
C
13

You're having difficulty defining zipE because it doesn't make semantic sense. If you consider the semantic definitions

Event a == [(Time, a)]
Event b == [(Time, b)]

there isn't a natural way to zip them, because in general each event will be at a different time.

It is possible to zip them using a sum instead of a product.

zipE :: Event a -> Event b -> Event (Either a b)
zipE aE bE = (Left <$> aE) `mappend` (Right <$> bE)

If you really need to have both a and b at the same time, the appropriate solution is to create a Behavior that accumulates over one or the other, or the merged Either stream as above.

edit: an example of one way to accumulate over the merged stream (untested). Other implementations are also possible. This doesn't make both events occur at the same time, rather it lets you combine the current state with past states so you can always have the most recently available of both Left and Right values.

currentAandB :: a -> b -> Event a -> Event b -> Event (a,b)
currentAandB a0 b0 aE bE = accumE (a0,b0) (mergefn <$> zipE aE bE)
    where
        mergefn (Left a)  (_,b) = (a,b)
        mergefn (Right b) (a,_) = (a,b)

It's still necessary to provide initial values for both Event streams. Think of it this way: if you've only had events from Event a, what value should the second part of the tuple have?

Casiecasilda answered 31/7, 2012 at 15:1 Comment(2)
John, thank you for helping me. I would like to know more about the appropriate answer you are mentioning. Could you please elaborate on how accumulating over one or the other makes both events occur at the same time? Sorry, if that's obvious. I just don't see it.Alsoran
@copton: I've posted an example of one way to do this. As for the initial values, if you think about the initial state of your problem you'll probably find a sensible answer. Or you can use a combination of Maybe, Data.Traversable.sequenceA, and filterJust to only produce output after you've received both an a and b.Casiecasilda

© 2022 - 2024 — McMap. All rights reserved.