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.

Home Page:https://reflex-frp.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Should buildDynamic should be :: PushM t (Dynamic t a) -> m (Dynamic t a) ?

oliver-batchelor opened this issue · comments

This allows the Event part of the output Dynamic to also depend on the Behaviour part of the input Dynamic. It's a generalisation of the existing buildDynamic..

It seems like it can simplify quite a few functions which otherwise resort to mapping the inner value of a Dynamic to another Dynamic and using join (quite a lot of primitives which aren't really needed)

Here's a challenge, write a version of the function below (holdDynUtil) which is constant/becomes constant (unsubscribes the input Dynamic) if the initial value or subsequent Event matches the predicate. It's possible but a lot of work, one solution I had Dynamic (Dynamic (Dynamic ...))

untilE :: (Reflex t, MonadHold t m, MonadFix m) => (a -> Bool) -> Event t a -> m (Event t a)
untilE f e = do
  last <- headE (ffilter f e)
  switchHold e (never <$ last)

-- Returns a dynamic which becomes constant once an event fires which matches the given predicate
-- Should be constant if the initial value matches the predicate (but isn't)
holdDynUntil :: (Reflex t, MonadHold t m, MonadFix m) => (a -> Bool) -> Dynamic t a -> m (Dynamic t a)
holdDynUntil f d = buildDynamic (sample (current d)) =<< untilE f (updated d)

Using proposed signature:

holdDynUntil f d = buildDynamic $ do 
      initial <- sample (current d)) 
      if (f initial) 
          then (pure initial)
          else holdDyn initial =<< untilE f (updated d)

I imagine there may be other functions which can be simplified this way?