我寫在Haskell一個遊戲程序,目前有這樣的哈斯克爾最有效的可變數據結構
data World = World {
worldPlayer :: !(IORef GameObject),
worldEntities :: ![IORef GameObject],
...
}
每次更新數據類型,下面的更新被寫入玩家IORef
:
updatePlayer :: GameObject -> [IORef GameObject] -> IO GameObject
在此功能中,它檢查每個物體的碰撞,然後移動播放器。 但我想updatePlayer函數是純的,所以我需要使用不同的數據結構。
最明顯的想法是從世界上採取[IORef GameObject]
,並通過在每個索引上調用readIORef
將其轉換爲IO [GameObject]
。但是這將是非常低效的。
另一種可能的方法,我發現這樣做是使用Data.Vector.MVector
和Data.Vector.Generic.unsafeUnfreeze
和unsafeFreeze
,其中有O(1)
性能做worldEntities :: !(MVector (PrimState IO) GameObject)
。問題是unsafeUnfreeze
和unsafeFreeze
只適用於某些數據類型。
我還發現IOArray
,所以我可以使用IOArray Int GameObject
,但我找不到將IOArray
轉換爲不可變結構的方法。
最後,我可以做IORef [GameObject]
或IORef (Vector GameObject)
,但我不確定這將是多高效。
什麼是最有效的方法來做到這一點?
實際上您是否需要可變數據結構?你確定每次更新都不夠快返回一個新的數據結構嗎? –
@TomEllis我認爲這將是非常低效的,如果你的意思是計算整個'世界'每一次更新。 – functorial
這取決於GameObject是什麼。返回一個新的對象肯定會比變異效率低,但可能不如你想象的那樣多,而且它確實容易得多!如果更新之間幾乎沒有變化,並且可以共享很多舊結構,它實際上可以非常快速。 –