我可以想象,對此的整體回答將推動我進入Functional Reactive Programming,但是...忍受着我一段時間。是否可以在GTK和Haskell中爲State monad中的數據創建TreeModel?
我也沒有這個問題的示例代碼。我用我的一些代碼在主題附近徘徊,但我一直堅守在它的IO monad中。
想象一下,我有一個應用程序,在這個應用程序中,我將建模一些複雜的狀態並將其放入整個應用程序狀態monad中。我這樣做是因爲我想要在覈心應用程序和特定用戶界面之間有一定程度的分離。
data S = S DataStore EventStream Sockets
type AppState m = StateT S m
(假設數據存儲,EventStream和套接字是所有的數據類型基本上做什麼,他們聽起來像:))
現在,說我想創建GTK(表中的TreeView,但沒有子節點)只能查看EventStream。我已經學會了這樣做,通過說listStoreNew event_stream >>= treeViewNewWithModel
(見http://markus.alyra.org/?p=1023在那裏我非常廣泛地談論這個設置的機制)。
但是,現在我有一個可變副本我的AppState monad中的數據。當應用程序關閉並執行一些將新數據附加到EventStream的操作時,該視圖中不會顯示該數據。我能想到的唯一方法就是在視圖中顯示除了對monad所做的更改外,還會發送一條消息,如listStoreInsert my_new_event
。這是可行的,但開始感覺笨拙。
更糟糕的是,這個神話般的樹視圖是一個管理視圖!這是可編輯!管理員說:「哦,那個事件有一些無效的數據,我想改變它!」。現在,我無法更改上面創建的ListStore中的數據。我可以創建回調,使更新沒有問題。但我無法想象如何將更新導入Global AppState Monad。
而那些最後幾個字顯示了問題的核心。如果我有一個全局的AppState Monad,那麼更新該monad的任何內容都必須在一行執行中,並且要查看monad的所有內容。 TreeView打破了這一點。當單元格在TreeView monad中編輯時,編輯處理程序完全在IO monad中運行,並且預計不會返回任何內容。最終數據類型爲IO()
。即使我有一些漂亮的方式從我的AppState中打開數據,然後執行編輯處理程序,然後將數據重新包裝到AppState中,應用程序的其他分支無法看到它。
即使我能想出如何創建自己的完全自定義的ModelView實例,該實例向我的AppState提供只讀視圖,但我無法想象如何使狀態更新可用於其他應用程序。
所以......
它甚至有可能以這種方式來建模GTK /哈斯克爾應用?或者,我是否走上了瘋狂之路?
我認爲你的例子是非常現實的(即沒有人爲的)。我完全沒有想過使用MVar。這可能是一個相當有趣的解決方案。 – 2012-07-11 15:10:23
我正在用手機寫這一切,所以請原諒這些混亂的解釋。之前我輸入的一個例子更具人爲性,涉及回調等不同的線程,但我意識到即使在具有不透明事件處理程序的單個線程上使用事件輪詢時也需要解決相同的問題。 – dflemstr 2012-07-11 15:55:35
週末我開始玩這個解決方案。我喜歡。不禁感慨我插入了一個額外的間接層,但我希望能夠解決這個問題,因爲我在Haskell上做得更好。 – 2012-07-23 21:18:34