8

私は反応バナナを学んでおり、サーバー側のアプリで使用するつもりです。私は RxJ のバックグラウンドを持っているので、Event をさまざまなコンビネーターと組み合わせることに慣れています。そこで、単純なイベント コンビネータの例から始めました。2 つの整数イベントを合計イベントに結合する単純なリアクティブ バナナの例を作成しようとしました。異なるイベントの値を結合できるようにするには、最初にそれらをビヘイビアにし、結合を行い、最後にそれを新しいイベントにする必要があることを理解しています。これが私がやった方法です:

-- Behaviors from Events e1, e2
let b1 = stepper 0 e1 :: Behavior Int
let b2 = stepper 0 e2 :: Behavior Int

-- Sum Behavior
let sumB = (+) <$> b1 <*> b2
-- Back to Event
let sumE = sumB <@ (e1 `union` e2)

完全な実行可能な例はGist 1594917にあります。

ここでの問題は、イベント (e1、e2) の 1 つに新しい値が表示されたときに sumE イベントが正しくトリガーされる一方で、古い値が含まれていることです。これはステッパーの仕組みによるものと思われます (イベント発生の「少し後」にビヘイビアーの値が変化します)。Behavior を Discrete に置き換えてみましたが、同じ結果になりました。

この種のイベントコンビネータを正しく動作させる簡単な方法はありますか?

4

1 に答える 1

6

あなたの診断は正確です。2 つのオプションがあります。 を介して Discrete から Event に戻るchangesか、累積イベントを作成できます。

Discrete から作業を戻す方がおそらく簡単です (そして、私が推奨する方法です)。やるだけ

-- Discretes from Events e1, e2
let d1 = stepperD 0 e1 :: Discrete Int
let d2 = stepperD 0 e2 :: Discrete Int

-- Sum Discrete
let sumD = (+) <$> d1 <*> d2
-- Back to Event
let sumE = changes sumD

NowsumEは、いつe1またはe2変更されるかを常に更新します。

別の方法では、受信イベントを累積関数に変換することにより、イベントのみを使用します。複雑に聞こえますが、コードはかなり単純です。

--convert each input into an accumulating tuple
let e1' = (\l (_,r) -> (l,r)) <$> e1
let e2' = (\r (l,_) -> (l,r)) <$> e2

let sumE = uncurry (+) <$> accumE (0,0) (e1' `union` e2')
于 2012-01-12T11:19:50.917 に答える