7

反応バナナで特定のタイプのイベントのスロットリングを実装したいと思います。通過した最後のイベントからデルタ秒未満で到着した場合、イベントが通過しないように動作する必要があります。通過させられない場合は保存され、最後に発生したイベントから delta 秒後に発生します。

以下は、タイムスタンプ付きの番号のリストに対してこれを実装するプログラムです。これを react-banana に変換することは可能でしょうか?

また、リアクティブバナナでは、他のイベントが入ってからx秒後にイベントを発生させるにはどうすればよいですか?

モジュールのメイン

import Data.List

-- 1 秒のスロットリング
-- ロジックは、最後の値が出力されてから 1 秒が経過するまで値を出力しないことです。

メイン :: 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) ] を出力する必要があります

テスト :: [(Double,Double)] -> [(Double,Double)]
テスト リスト = gv (concat xs)
       どこ
               (v, xs) = mapAccumL f (-50,Nothing) リスト
               g (t, Just x) ys = ys ++ [ (t+1,x) ]
               g_ys = ys
               f (lasttime, Just holdvalue) (t,x) = if t > (lasttime+1) then
                               t > (前回 + 2) の場合
                                       ( (t, Nothing), [ (lasttime+1,holdvalue), (t,x)] )
                               else ( (lasttime+1, Just x) , [ (lasttime+1,holdvalue) ] )
                       そうしないと        
                               ((前回, Just x), [] )
               f (lasttime, Nothing) (t,x) = if t > (lasttime+1) then
                        ( (t,Nothing) , [ (t, x ) ] )
                        else ( (前回, Just x), [] )
4

2 に答える 2

3

Reactive-banana-0.6 の時点で、希望する機能を実装することは間違いなく可能ですが、少し複雑です。

基本的に、wxHaskell のような外部フレームワークを使用してタイマーを作成し、それを使用してイベントをスケジュールします。Wave.hsの例は、その方法を示しています。

現時点では、リアクティブ バナナ ライブラリ自体に時間の概念を含めないことにしました。その理由は単純に、異なる外部フレームワークには異なる解像度または品質のタイマーがあり、すべてに適合する 1 つのサイズは存在しないためです。

時間とタイマーを処理する一般的なヘルパー関数をライブラリ自体に追加するつもりですが、さまざまなタイマーでジェネリックにする良い方法を見つけて、提供できる保証を見つけ出す必要があります。

于 2012-06-07T13:35:48.817 に答える
1

わかりました、質問で説明したことをなんとか実装できました。私は、反応を介してタイマーを制御するために 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
于 2012-06-07T20:28:22.497 に答える