反应 - 香蕉节流事件 [英] reactive-banana throttling events
问题描述
我想在反应式香蕉中实施某种类型的事件限制。它应该起作用,以使得如果从最后一次通过的事件到达的时间少于三秒,事件就不会通过。如果它没有通过,那么它将被存储并在最后一次触发事件的增量秒后触发。
下面是一个程序,用于实现这个时间戳数字列表。这是否有可能将其转化为反应性香蕉?
另外,在反应性香蕉中,在其他事件进入后x秒钟内如何发生事件? p>
模块Main其中
导入Data.List
- 1秒throtling
- 逻辑在输出最后一个值之后的1秒之前从不输出一个值。
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)]
- 应该输出[(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)
其中
(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),[])
好的,我设法实现了我在我的问题中描述的内容。我不是很高兴IO需要通过反应来控制计时器。我不知道是否可以用节气门标记油门:: Event ta - > Int - > Event ta ...
ps:我很新手在Haskell中,所以代码可能会更紧凑或优雅。
{----------- -------------------------------------------------- ----------------
-------------------------- -------------------------------------------------- - }
{ - #LANGUAGE ScopedTypeVariables# - } - 允许forall t。NetworkDescription t
import Graphics.UI.WX隐藏(事件)
导入无效。 Banana
import Reactive.Banana.WX
import Data.Time
{---------------------- -------------------------------------------------- -----
主
------------------------------------ ------------------------------------------}
数据ThrottledValue a = FireStoredValue a | FireNowAndStartTimer a | HoldIt a |停止导出显示
数据ThrottledEvent a = TimerEvent | RealEvent派生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]
让networkDescription :: forall t。 NetworkDescription t()
networkDescription = do
slEv< - event0 sl1命令
tick< - event0 t命令
slB< - 行为sl1选择
let throttledEv,reactimates)= throttle(slB <@slEv)tick t 100
reactimates
reactimates $ fmap(\ x - > set sl2 [selection:= x])throttledEv
net < - 编译网络描述
启动网络
throttle :: Event ta - >事件t() - >定时器 - > Int - > (事件ta,NetworkDescription t())
throttle ev tick timer dt =(throttledEv,reactimates)
其中
all = union(fmap(\ x-> RealEvent x)ev) (fmap(\ x - > TimerEvent)tick)
result = accumE已停止$ fmap h全部
其中
h(RealEvent x)Stopped = FireNowAndStartTimer x
h TimerEvent Stopped = Stopped
h(RealEvent x)(FireEowAndStartTimer _)= HoldIt x
h TimerEvent(FireNowAndStartTimer _)=已停止
h(RealEvent x)(HoldIt _)= HoldIt x
h(TimerEvent) 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停止结果
reactimate $ filterJust $ fmap开始结果
filterFired(FireStoredValue a)=只需
filterFired(FireNowAndStartTimer a)=只需
filterFired _ = Nothing
throttledEv = filterJust $ fmap filterFired result
$ b startTimer t dt = set t [enabled:= True,interval:= dt]
stopTimer t = set t [enabled := False]
resetTimer t dt = stopTimer t>> startTimer t dt
I would like to implement a certain type of throttling of events in reactive-banana. It should work such that an event is not let through if arrives at less then delta seconds from the last event that passed through. If it is not let through then it is stored and is fired after delta seconds from the last fired event.
Below is a program that implements this for lists of time stamped numbers. Would it be possible to translate this to reactive-banana ?
Also, in reactive-banana how do I fire an event x seconds after some other event comes in ?
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 = g v (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), [] )
Ok, I managed to implement what I described in my question. I'm not so happy that IO is needed to control the timer via reactimate. I wonder if it would be possible to have a throttle with signature throttle::Event t a -> Int -> Event t a ...
ps: I'm very novice in Haskell so the code could probably a lot 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 t a -> Event t () -> Timer -> Int -> (Event t a, 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
这篇关于反应 - 香蕉节流事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!