Looking for `flatten :: Event [a] -> Event a` in Reactive Banana
Asked Answered
I

1

6

I'm looking for something like flatten :: Event [a] -> Event a (swap [] with Foldable f => f if you want) which would generate a separate event for each a in an Event's list, like split in an old version of sodium.

I suspect that this is somehow possible with switchE, but then I'd need a function of type [a] -> Event a.

I could possibly craft that myself with newEvent, but is there a function built-in to reactive-banana?

Edit:

Actually, I'm not so sure I can implement that with newEvent after all.

flatten :: Foldable f => f a -> Banana.MomentIO (Banana.Event a)
flatten xs = do
  (event, fire) <- Banana.newEvent
  liftIO $ forkIO $ mapM_ fire xs
  return event 

Will fire block until there are subscribers or will it just return immediately if there aren't any?

Edit 2:

Looking at the implementation of newAddHandler my implementation above won't work, because all events are possibly fired before any handlers can register.

Interplay answered 29/4, 2016 at 16:46 Comment(0)
B
6

This appears to be impossible. According to the notes in Heinrich Apfelmus's blog, Event doesn't support simultaneous occurrences. This is a relatively recent change; the post is dated August last year and v1.0 was released in October. It certainly wasn't the case when I originally learned Reactive Banana a few years ago.

But Event [a] seems like a reasonable way to represent a set of coincidental events in the first place. Why do you need to flatten it?

Basilbasilar answered 29/4, 2016 at 17:51 Comment(9)
I want to perform an IO action for each one of those as (fetch/clone git repositories) and then execute downstream code after each one (e.g. build and benchmark the project). I'd prefer to do it in a 'depth-first' (running corresponing fetch and build consecutive) rather than 'breadth-first' manner (running all fetches, then running all builds). There are also other event sources which produce single as, but I could wrap that in singleton lists of course.Interplay
Actually, I think doing IO is the only thing where it matters semantically.Interplay
I think fmap (traverse (clone >=> build)) :: Event [Project] -> Event (IO ()) would do that, no?Basilbasilar
Yeah, but I'd rather separate clone and build into their own events/arrows, because build can be also triggered by other events. But thanks for the suggestions, I'll go try something.Interplay
Just make clone and build into separate functions , as I suggested above, and fmap (traverse build) over the other events that could trigger a buildBasilbasilar
I'll run with that! Although that leaves me a little puzzled wrt. how I should structure my application. Originally I thought I could just have many modules exporting Event a -> MomentIO (Event b) arrows hiding IO and state in a well-behaved way. Now I have to 'break' that rule with build, although it seems OK because it is a sink in the network anyway.Interplay
Event doesn't support simultaneous occurrences. This is also the case for more recent versions of sodium, by the way.Hideaway
@Sebastian That's not how I'd structure the code. Confine your use of the Reactive.Banana.Frameworks module to the entry point of your application, which should just consist of calls to fromAddHandler (to bind inputs) and reactimate (to bind outputs). Keeping MomentIO out of your library modules promotes composability.Basilbasilar
Thanks for your suggestions. I got the network to do what I want now.Interplay

© 2022 - 2024 — McMap. All rights reserved.