2014-11-20 71 views
0

我使用國家Monad維護我的世界,並使用光澤圖形。光澤在每個「打勾」之間傳遞一個「世界」對象以繼續前進。問題是,對於這個工作,我需要能夠定義:不能逃脫國家Monad

wsToPicture :: WorldState() -> Picture 

其中

World = data World = World { ... } 
WorldState = type WorldState = State World 
Picture = Gloss's representation of a graphic. 

我能得到的最好的是:

wsToPicture :: WorldState() -> Picture 
wsToPicture ws = toPicture . execState ws startingWorld 

其中

startingWorld = The very initial state of the world 
toPicture = World -> Picture (Defined elsewhere) 

其中至少編譯,但世界重置每打勾。把startingWorld放在那裏純粹是爲了編譯;我知道這是錯的。如果我沒有當前的World給出它,我如何才能擺脫State monad?唯一可用的世界是在WorldState之內,我不能使用get來提取它,因爲只要我使用>>=,函數必須返回WorldState

我假設我誤解了一些東西。有人可以闡明可能的情況嗎?

+1

你嘗試過'wsToPicture :: WorldState Picture'; 'wsToPicture = fmap toPicture get',那麼你可以把所有的東西都保存在monad狀態中,而不是試圖轉義它。 – bheklilr 2014-11-20 17:34:14

+0

另一個定義是'wsToPicture = do {ws < - get;返回$ toPicture ws}' – bheklilr 2014-11-20 17:34:39

+0

@bheklilr:gloss預計世界 - >圖片IIRC。 – Zeta 2014-11-20 17:34:51

回答

3

這看起來像是xy problem。光澤已經帶有狀態你,這是給你的更新和事件處理功能的世界:

update :: TimeDiff -> World -> World 
handle :: Event -> World -> World 
--     ||||| ^^^^^ next world 
--     ^^^^^ current world 

您可能使用State爲你的世界的簡單修改。這是完全有可能在updatehandle

update :: TimeDiff -> World -> World 
update dt world = flip execstate world $ do 
    -- do something with world, e.g. 
    modify (\w -> w {players = round (exp dt) }) 

但是你World本身不應該基於StateStateT

+0

謝謝。這實際上是我最初設置的,但它似乎很笨重,不得不將monad留在現有的處理程序上,只能在下一個處理程序開始時重新輸入它。我認爲留在它會清理它,但顯然不是。你和bheklilr建議鏡頭,所以我會接下來看看它。謝謝。 – Carcigenicate 2014-11-20 18:14:26

+0

@Carcigenicate:鏡頭庫看起來可能有點壓倒一切。看看Edward Kmett的視頻或fpcomplete的博客文章。 – Zeta 2014-11-20 18:16:55

+0

謝謝。我可能只是開始切入,開始一個新的項目,模擬理想的用例。我讀到有人使用鏡頭來模擬由深度嵌套對象表示的房屋自動化系統。也許我會放棄這一點。 – Carcigenicate 2014-11-20 18:19:17