mig*_*rao 7 haskell frp reactive-programming
我想在反应香蕉中实施某种类型的事件限制.它应该起作用,如果从最后一个通过的事件到达少于delta秒,则不通过事件.如果它没有通过那么它被存储并在从最后一个被触发的事件开始的delta秒之后被触发.
下面是一个程序,用于为带有时间戳的数字列表实现此功能.是否有可能将其转化为反应性香蕉?
此外,在反应性香蕉中,如何在其他事件进入后x秒发射事件?
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), [] )
好的,我设法实现了我在问题中描述的内容。我不太高兴需要 IO 来通过重新启动来控制计时器。我想知道是否有可能有一个带有签名throttle::Event ta -> Int -> Event ta ...的油门
ps:我对 Haskell 很陌生,所以代码可能会更紧凑或更优雅。
{-----------------------------------------------------------------------------
------------------------------------------------------------------------------}
{-# 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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
367 次 |
| 最近记录: |