Banana Throttle Reaction Events

I would like to implement a certain type of throttling event in a reactive banana. It should work in such a way that the event is not skipped if it arrives in less than delta seconds from the last event. If it is not skipped, it is saved and started after delta seconds from the last past event.

Below is a program that implements this for time stamped lists of numbers. Can this be translated into reactive banana?

Also, in a reactive banana, how do I fire an event a few seconds after some other event happens?

 module Main where import Data.List - 1 second throtling - logic is to never output a value before 1 second has passed since last value was outputed.  main :: IO () main = print $ test [(0.0, 1.0), (1.1, 2.0), (1.5,3.0), (1.7,4.0), (2.2, 5.0)] --should output [(0.0, 1.0), (1.1, 2.0), (2.1,4.0), (3.1, 5.0)] test :: [(Double, Double)] -> [(Double, Double)] test list = gv (concat xs) where ( v, xs) = mapAccumL f (-50, Nothing) list g (t, Just x) ys = ys ++ [(t + 1, x)] g _ ys = ys f (lasttime, Just holdvalue) (t, x) = if t> (lasttime + 1) then if t> (lasttime + 2) then ((t, Nothing), [(lasttime + 1, holdvalue), (t, x)]) else ((lasttime + 1 , Just x), [(lasttime + 1, holdvalue)]) else ((lasttime, Just x), []) f (lasttime, Nothing) (t, x) = if t> (lasttime + 1) then (( t, Nothing), [(t, x)]) else ((lasttime, Just x), []) 
+7
source share
2 answers

Well, I managed to implement what I described in my question. I am not very pleased that IO is needed to control the timer through reaction. I wonder if it is possible to have a choke with a signal choke :: Event ta → Int → Event t a ...

ps: I am very new to Haskell, so the code can be much more compact or elegant.

{----------------------------------------------------------------------------- ------------------------------------------------------------------------------} {-# LANGUAGE ScopedTypeVariables #-} -- allows "forall t. NetworkDescription t" import Graphics.UI.WX hiding (Event) import Reactive.Banana import Reactive.Banana.WX import Data.Time {----------------------------------------------------------------------------- Main ------------------------------------------------------------------------------} data ThrottledValue a = FireStoredValue a | FireNowAndStartTimer a| HoldIt a | Stopped deriving Show data ThrottledEvent a = TimerEvent | RealEvent a deriving Show main = start $ do f <- frame [text := "Countercesss"] sl1 <- hslider f False 0 100 [] sl2 <- hslider f False 0 100 [] set f [ layout := column 0 [widget sl1, widget sl2] ] t <- timer f [] set t [ enabled := False ] let networkDescription :: forall t. NetworkDescription t () networkDescription = do slEv <- event0 sl1 command tick <- event0 t command slB <- behavior sl1 selection let (throttledEv, reactimates) = throttle (slB <@ slEv) tick t 100 reactimates reactimate $ fmap (\x -> set sl2 [selection := x]) throttledEv net <- compile networkDescription actuate net throttle::Event ta -> Event t () -> Timer -> Int -> (Event ta, NetworkDescription t () ) throttle ev tick timer dt = (throttledEv, reactimates) where all = union (fmap (\x-> RealEvent x) ev) (fmap (\x -> TimerEvent) tick) result = accumE Stopped $ fmap h all where h (RealEvent x) Stopped = FireNowAndStartTimer x h TimerEvent Stopped = Stopped h (RealEvent x) (FireNowAndStartTimer _) = HoldIt x h TimerEvent (FireNowAndStartTimer _) = Stopped h (RealEvent x) (HoldIt _) = HoldIt x h (TimerEvent) (HoldIt y) = FireStoredValue y h (RealEvent x) (FireStoredValue _) = HoldIt x h (TimerEvent) (FireStoredValue _) = Stopped start (FireStoredValue a) = Just $ resetTimer timer dt start (FireNowAndStartTimer a) = Just $ resetTimer timer dt start _ = Nothing stop Stopped = Just $ stopTimer timer stop _ = Nothing reactimates = do reactimate $ filterJust $ fmap stop result reactimate $ filterJust $ fmap start result filterFired (FireStoredValue a) = Just a filterFired (FireNowAndStartTimer a) = Just a filterFired _ = Nothing throttledEv = filterJust $ fmap filterFired result startTimer t dt = set t [ enabled := True, interval := dt ] stopTimer t = set t [ enabled := False ] resetTimer t dt = stopTimer t >> startTimer t dt 
+1
source

Compared to reactive banana-0.6, it is certainly possible to realize the desired functionality, but this is slightly related.

Basically, you use an external infrastructure like wxHaskell to create a timer that you can then use to schedule events. The Wave.hs example demonstrates how to do this.

At the moment, I decided not to include the concept of time in the reactive banana library. The reason is that different external frames have timers of different resolution or quality, there is no single size that would fit all.

I'm going to add common helper functions that relate to time and timers for the library itself, but I still need to find a good way to make it common for different timers and figure out what guarantees I can provide.

+3
source

All Articles