reflex-frp / reflex

Interactive programs without callbacks or side-effects. Functional Reactive Programming (FRP) uses composable events and time-varying values to describe interactive systems as pure functions. Just like other pure functional code, functional reactive code is easier to get right on the first try, maintain, and reuse.
https://reflex-frp.org
BSD 3-Clause "New" or "Revised" License
1.07k stars 149 forks source link

Running programs with an occurrence at "now" #442

Closed parenthetical closed 4 years ago

parenthetical commented 4 years ago

I need to run a program returning an event in a way that I can tell what the value of a possible event occurrence at "now" is, maybe even allowing an input event to have an occurrence at now.

For example with a function runE behaving like so:

runE :: (t ~ SpiderTimeline Global, m ~ SpiderHost Global)
       => (Event t a -> m (Event t b))
       -> [a]
       -> IO [Maybe b]
runE = ...

where

runE (\e -> do
        n <- now
        pure . fmap getSum $ (Sum 1 <$ n) <> (Sum <$> e))
   [1,1]

produces: [2,1].

What would be the best way to implement such a function?

parenthetical commented 4 years ago

Coming back to this, the following seems to do the trick!

runE :: (t ~ SpiderTimeline Global)
       => (Event t a -> PushM t (Event t b))
       -> [a]
       -> IO [Maybe b]
runE p input = runSpiderHost $ do
  let p' e =
        switchHoldPromptOnly never
        . pushAlways (const (p e))
        =<< headE e
  (inE, trigRef) <- newEventWithTriggerRef
  outE <- runHostFrame (p' inE)
  outHnd <- subscribeEvent outE
  forM input (\a -> fireEventRefAndRead trigRef a outHnd)