複数のウィンドウと単一のデータ構造を反応的なバナナで処理する方法

私はどのように反応性バナナが次のような状況に対処するように設計されているのだろうかと思います:

私は中央のデータ構造を持っているとしましょう。ユーザは、データを表示し、ユーザがそれを変更できるようにする任意の数の異なるタイプのウィンドウを自由に開閉することができる。

だから、この性質を考えると、大きなネットワークを作るのはうまくいくとは思えません。これは、各ウィンドウがネットワークを持ち、何とか接続された場所ですか?

このような状況では、誰もが更新を送った1つのチャンネルの裏にデータ構造を置いていました。そして、データ構造は、ウィンドウがすべて "聴いた"という更新(fireイベント)を "公開"します。

2

2 答え

MVCアーキテクチャに似たものを使っている私のプロジェクトの1つに、関連する問題があります。中央のデータ構造は、

-- the data is a tree, and it's kept as a zipper to the current node
Discrete MyDataZip

ここに私のコントローラ宣言の削除版があります:

data Controller st = Controller {
  dState      :: Discrete st
 ,eUpdateZip  :: Event (MyDataZip -> MyDataZip)
 ,eResponse   :: Event (IO ())
 ,bDiagChange :: Behavior (Diagram Cairo R2 -> Diagram Cairo R2)
 }

構築されると、ほとんどのコントローラは dZip :: Discrete MyDataZip への参照を取得しますが、直接変更する方法はありません。コントローラが更新を指定する唯一の方法は、コントローラデータ構造内の eUpdateZip ストリームを経由する方法です。

Multiple controllers are assembled into a graph, which is just a list of Controllers placed in an existential type wrapper data EControl = forall st. EControl (Controller st). I just mconcat all of the individual eUpdateZip parameters to get a single stream of Event (MyDataZip -> MyDataZip) which is used to create the Discrete MyDataZip. The whole thing works because creating new controllers is pure, so it can be done in the same let-binding, allowing the recursive reference.

新しいウィンドウとその他のIOタスクを開くことは、 eResponse ストリームで行われます。これは mconcat dと同様に、

詳細については、 darcsレポを調べることができます。詳しくは、「src/Jaek/UI/Controllers」を参照してください。/"と" src/Jaek/UI/ControlGraph.hs "を参照してください。

編集:中心的な問題は、1つの大きなネットワークが開発者のPOVからかなり扱いにくいことです。ネットワークを分割することで複雑さを軽減することができます。これは良い解決策です。私の設計では、リアクティブな参加者に特定のコントローラモデルを適用させ、それらのモデルが相互作用するための明確な手段を作成することで、ネットワークに多くの構造を導入しました。私のコントローラは永続的なので、すべて静的に設定されていますが、動的に行うこともできます。コントローラマネージャを1つのスレッドで実行し、新しいコントローラを生成したアクション(新しいウィンドウを開くなど)メッセージをスレッドに送信して、新しいコントローラを作成します。

3
追加された

現時点では、外部イベントをコンパイル後にイベントネットワークに追加または削除することはできません(リアクティブバナナバージョン0.4.3以降)。言い換えれば、あなたの仕事を単一のイベントネットワークに記述することは不可能です。ただし、外部イベントまたは複数のイベントネットワークを利用することができ、次のようなソリューションが得られます。

  • ウィンドウの動的なコレクションをイベントソースの静的なセット(別名 AddHandler )にマップします。
  • または、ウィンドウごとに1つのイベントネットワークを使用して、外部イベントソース経由で通信できるようにします。
  • 新しいウィンドウが追加または削除されるたびに、単一のイベントネットワークを再コンパイルします。残念ながら、内部状態は失われますので、明示的にして外部で取得する必要があります( IORef など)。 (これはおそらく最も満足のいく解決策です)。
1
追加された
@Charlesはい、動的イベント切り替えでこれが可能になりました。 BarTab.hs の例は、同様の状況を示していますが、ウィンドウの数は可変ではありませんが、可変数のテキスト入力ボックスがあります。
追加された 著者 Heinrich Apfelmus,
reactive-banana 0.8の話は同じですか? execute と友人がいたら、もっとクリーンな方法でこれを行うことができるのだろうかと思います。
追加された 著者 ocharles,