2012-07-31 12 views
7

私は一般的に反応性のバナナとFRPを初めて使用しています。zipE :: Event t a - >イベントt b - >イベントt(a、b)

my projectGDB/MIフロントエンド)GUIとフロントエンドロジックモジュールの両方にリアクティブバナナ(バージョン0.6.0.0)を使用しています。前者は素晴らしいですが、後者のために私は明らかに追加のコンビネータが必要です。

zipE :: Event t a -> Event t b -> Event t (a, b)のいずれかです。残念ながら、私が思い付くことができるすべてはchangesを使用し、イベントタイプでジェネリックではありませんNetworkDescriptionモナドでのソリューションです:もちろん

zipE :: Event t Int -> Event t String -> NetworkDescription t (Event t (Int, String)) 
zipE ea eb = changes $ (,) <$> stepper 0 ea <*> stepper "" eb 

、私はこれで満足していません。そこで、私はchangesを使わずにジェネリックなzipE関数を実装する方法を尋ねたいと思っていました(非GUIの目的で使うことはお勧めしません)。

他の試みは失敗しました。 1つシフトされたタプルの最初の要素で

zipE :: Num a => Event t a -> Event t b -> Event t (a,b) 
zipE ea eb = apply (stepper (0,) ((,) <$> ea)) eb 

結果 - 私はstepperによって導入された「わずかな遅れ」による推測。しかし、私はstepper(またはそれに関してはaccumB)のイベントなしで動作を取得する方法は見当たりませんし、動作のないイベントにどのように機能を適用するのか分かりません。全体として、私はジェネリック型の場合にステッパーに初期値を与える方法を見ていません。

+2

'ea'と' eb'は同時に起動しません。 (彼らが同じ基本イベントから派生しているので、同時に発射することが分かっている場合は、その基本イベントを再処理するのが最善でしょう。)火災が発生したときに何が起こりたいのか、 t? – dave4420

+0

デイブ、そうです。イベントネットワークには別のデザインが必要です: - /これを指摘していただきありがとうございます。 – copton

+2

私は本当に別のイベントネットワークが必要でした。最初は、2つのイベントを圧縮してタプルを 'f ::(a、b) - > IO()'に送りたいと思っていました。私は今代わりに 'f :: a - > b - > IO()'と '$(f <$> stepper 0 aE)<@> bE'を反応させます。 – copton

答えて

13

zipEは意味が分かりませんので、定義するのが難しいです。意味定義を考慮すると、一般に各イベントは異なる時刻になるため、意味的な定義を考慮すると、自然な方法でそれらを解凍することはできません。

商品の代わりに合計を使用してそれらを圧縮することは可能です。

zipE :: Event a -> Event b -> Event (Either a b) 
zipE aE bE = (Left <$> aE) `mappend` (Right <$> bE) 

あなたが本当に同時にabの両方を持っている必要がある場合は、適切な解決策は、上記のように、どちらか一方、またはマージされたEitherストリーム上に蓄積Behaviorを作成することです。

edit:マージされたストリーム(未テスト)に累積する1つの方法の例。他の実装も可能である。これにより、両方のイベントが同時に発生するのではなく、現在の状態と過去の状態を組み合わせることができるため、常に最新の値をLeftRightの両方で使用できるようになります。

currentAandB :: a -> b -> Event a -> Event b -> Event (a,b) 
currentAandB a0 b0 aE bE = accumE (a0,b0) (mergefn <$> zipE aE bE) 
    where 
     mergefn (Left a) (_,b) = (a,b) 
     mergefn (Right b) (a,_) = (a,b) 

Eventストリームの初期値を指定する必要があります。このように考える:Event aのイベントしかない場合、タプルの第2部分にはどのような値が必要ですか?

+0

ジョン、私を助けてくれてありがとう。あなたが言及している適切な答えについてもっと知りたいと思います。あなたはどちらか一方の上に蓄積することによって両方の出来事が同時に起こる方法を詳しく教えていただけますか?申し訳ありませんが、それは明らかです。私はそれを見ない。 – copton

+1

私が示唆しているものとまったく同じです。 – Conal

+0

@copton:これを行う方法の例を掲載しました。初期値については、問題の初期状態を考えるなら、おそらく分かりやすい答えがあるでしょう。あるいは 'Maybe'、' Data.Traversable.sequenceA'、 'filterJust'の組み合わせを使用して、' a'と 'b'の両方を受け取った後にのみ出力を生成することができます。 –

関連する問題