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
、Controller データ構造内のストリームを使用することです。
複数のコントローラーが 1 つのグラフにまとめられます。これは、存在型のラッパーに配置されたコントローラーの単なるリストですdata EControl = forall st. EControl (Controller st)
。個々のパラメータをmconcat
すべて取得して、. 新しいコントローラーの作成は純粋であるため、すべてが機能し、同じ let バインディングで実行でき、再帰参照が可能になります。eUpdateZip
Event (MyDataZip -> MyDataZip)
Discrete MyDataZip
新しいウィンドウを開くなどの IO タスクはeResponse
ストリームで行われ、同様にmconcat
d されてから に渡されreactimate
ます。
詳細については、darcs リポジトリを調べることができます。「src/Jaek/UI/Controllers/」および「src/Jaek/UI/ControlGraph.hs」を参照してください。
編集: 中心的な問題は、1 つの大きなネットワークが開発者の視点からはかなり扱いにくいことです。ネットワークをセグメント化することで複雑さを軽減できますが、これは優れたソリューションです。私の設計では、リアクティブな参加者を特定のコントローラー モデルに適合させ、それらのモデルが相互作用するための明確に定義された手段を作成することで、ネットワークに多くの構造を導入しました。私のコントローラーは永続的であるため、すべて静的にセットアップされますが、動的に行うこともできます。その場合、おそらくコントローラーマネージャーを 1 つのスレッドで実行し、新しいコントローラーを生成するアクション (新しいウィンドウを開くなど) は、新しいコントローラーを作成するスレッドへのメッセージ。