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?