これに対する全体的な答えが私を関数型リアクティブプログラミングに押しやるだろうと想像しますが、...ちょっと我慢してください。
この質問のサンプルコードもありません。私は自分のコードのいくつかでトピックの近くをさまよいましたが、それで IO モナドにしっかりととどまりました。
やや複雑な状態をモデル化し、それを全体的な Application State モナドに入れるアプリケーションがあると想像してください。コア アプリケーションと特定のユーザー インターフェイスとの間に一定レベルの分離が必要なため、このようにしています。
data S = S DataStore EventStream Sockets
type AppState m = StateT S m
(DataStore、EventStream、および Sockets はすべて、基本的にそのように聞こえるデータ型であると仮定します:))
ここで、EventStream のみを表示する GTK (TreeView、子ノードなし) でテーブルを作成したいとします。私はすでにそれを行うことを学びましたlistStoreNew event_stream >>= treeViewNewWithModel
( http://markus.alyra.org/?p=1023を参照してください。ここでは、これを設定する仕組みについてかなり詳しく説明しています)。
しかし、今では AppState モナドにあるデータの変更可能なコピーがあります。アプリケーションがオフになり、EventStream に新しいデータを追加する何かを実行すると、それはビューに表示されません。私が考えることができる唯一の方法はlistStoreInsert my_new_event
、モナドに加えられた変更に加えて、のようなメッセージでそれを送信することです。それは可能ですが、不器用に感じ始めています。
さらに悪いことに、この神話上のツリー ビューは管理ビューです。編集可能です!管理者は、「ああ、そのイベントには無効なデータが含まれているので、変更したい!」と言います。これで、上で作成した ListStore 内のデータを問題なく変更できます。問題なく更新を行うコールバックを作成できます。しかし、アップデートを Global AppState Monad に入れる方法はまったく考えられません。
そして、これらの最後のいくつかの言葉は、問題の核心を示しています。グローバルな AppState モナドがある場合、そのモナドを更新するものはすべて、モナドを表示したいすべてのものと一緒に 1 行で実行する必要があります。TreeView はそれを破ります。TreeView モナドでセルが編集されると、編集ハンドラーは完全に IO モナドで実行され、何も返さないことが期待されます。終了データ型はIO ()
. AppState からデータをアンラップし、編集ハンドラーを実行して、AppState でデータを再ラップする気の利いた方法があったとしても、アプリケーションの他のブランチはそれを見ることができませんでした。
AppState への読み取り専用ビューを提供する独自の完全にカスタムな ModelView インスタンスを作成する方法を理解できたとしても、アプリケーションの残りの部分で状態の更新を利用できるようにする方法が思い浮かびません。
そう...
この方法で GTK/Haskell アプリケーションをモデル化することさえ可能ですか? それとも、私は狂気への道を進んでしまったのでしょうか?