2013-06-23 8 views
5

のは、私がIO関数を使用してイベントを変換する方法は?

e1 :: Event t A 
f :: A -> IO B 

は私がe1によってトリガされる

e2 :: Event t B 

を作成する必要があり、かつその値はイベント発生時にe1の値にfを実行することによって決定されているとしましょう。

ダイナミックイベントの切り替えとハンドラの使用による2つの可能性がある方法がありますが、そのような単純なことはどちらも複雑すぎます。

これを行う適切な方法は何ですか?

+0

は 'unsafePerformIO'オプションですか? – Ankur

+1

@Ankur:いいえ、それは間違いなく「適切な方法」ではありません。 –

答えて

2

機能fには副作用があるため、実際には簡単なことではありません。主な理由は、副作用の順序が複数の同時イベントがある場合には明確に定義されていないことです。より一般的には、イベントでIOアクションを処理するための良いセマンティクスを考えることができませんでした。したがって、反応性バナナは、この状況に対して純粋なコンビネータを提供しません。

これをやりたければ、副作用の順番を決定する、より精巧なメカニズムを使用する必要があります。たとえば、あなたはreactimateを使用してコンビネータ

mapIO :: Frameworks t => (a -> IO b) -> Event t a -> Moment t (Event t b) 
mapIO f e1 = do 
    (e2, fire2) <- liftIO newAddHandler 
    reactimate $ (\x -> f x >>= fire2) <$> e1 
    fromAddHandler e2 

を書くことができますしかし、結果イベントe2は、もはや入力イベントe1と同時であるとして、これは予期しない結果が得られないかもしれないことに注意してください。たとえば、動作が変更され、その他の副作用が実行されている可能性があります。

+1

FRPの目的はIOを扱うことであるから、IOアクションは「ファーストクラス」ではないという点で、少し驚くべきことです。 特に、同時イベントには順序があります - それで、対応するエフェクトに同じ順序を使用しないのはなぜですか? 私はこれが強打ではないことを理解します。 IOアクションは他のイベントを引き起こす可能性があり、イベントを「同時」とみなすには時間がかかりすぎます...しかし、私はその責任を負うことができます。つまり、私はイベントハンドラを呼び出さないことを約束し、そのアクションは私の目的にとって「瞬間的」になるでしょう。それはまだ不可能ですか?どうして? –

+1

まあ、同時のイベントはすべてのイベントでオーダーを持つかもしれませんが、グローバルオーダーはありません。 'ex'と' ey'が同時に発生する 'union ex ey'と' union ey ex'の2つのイベントを考えてみましょう。プログラムは同時に両方の組み合わせをうまく使用することができますが、同時に発生するイベントの順序はそれぞれ異なります。より一般的には、イベントでIOアクションを注文するための良いセマンティクスを見つけることができなかったため、反応性バナナはそれらをサポートしていません。 (私はこの点を強調するために私の答えを更新しました) –

+2

一般的にFRPについては、これが失望していないことを願っていますが、IOはあまりIOではなく、事象や時変値で計算することに焦点を当てています。つまり、あなたはしばしば境界でIOとインターフェースする必要があります。多くの可能性があります: 'reactimate'または' mapIO'コンビネーター、 'Reactive.Banana.Frameworks 'の' mapIO'コンビネーター。AddHandler'モジュールを使用してイベントを修正してからFRPワールドに渡すことができます。 –

1

freactimate(これはイベントネットワークからIOを処理する「適切な方法」と理解しています)で呼び出すことができますか?そこで、イベントネットワークにタイプEvent t Bの新しいイベントを発生させます。または、これはあなたが「ハンドラを使用する」という意味ですか?

+0

はい、それは私が「ハンドラを使う」という意味です。 –