I'm using Reflex within Haskell, and am trying to create an event which fires (for question purposes) a set period of time after another, let's say 2 seconds. However, the counter should reset whenever the original event fires, so that if the original event fires twice 1 second apart, there should only be one firing of the second event: 2 seconds after the last original event.
I've managed to implement this behaviour with
delayedReset :: MonadWidget t m => Event t () -> m (Event t ())
delayedReset ev = fmap (switch . current) . widgetHold (return never) $ timer <$ ev
where
timer = delay 2 =<< getPostBuild
but it seems overkill to use widgetHold; it seems that we should only really need a MonadHold constraint. Is there a more idiomatic way to write this function?
It seems that I missed the rather obvious:
delayedReset :: MonadWidget t m => Event t () -> m (Event t ())
delayedReset ev = do
endEv <- delay 2 ev
countDyn <- foldDyn ($) (0 :: Int) $ leftmost
[ (+1) <$ ev, subtract 1 <$ endEv ]
return $ attachPromptlyDynWithMaybe ifZero countDyn endEv
where
ifZero 0 a = Just a
ifZero _ _ = Nothing
The constraints can be relaxed, though this makes them much more verbose.
In the end, though, I went with my first solution. I think the performance hit is minor enough and it simplifies some other aspects of the program.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With