Haskell最有效的可变数据结构

fun*_*ial 1 arrays performance haskell functional-programming data-structures

我正在Haskell中编写一个目前有类似数据类型的游戏程序

data World = World {
    worldPlayer :: !(IORef GameObject),
    worldEntities :: ![IORef GameObject],
    ...
}
Run Code Online (Sandbox Code Playgroud)

每次更新时,以下更新都会写入播放器IORef:

updatePlayer :: GameObject -> [IORef GameObject] -> IO GameObject
Run Code Online (Sandbox Code Playgroud)

在此函数中,它检查每个对象的碰撞,然后移动播放器.但我希望updatePlayer函数是纯粹的,所以我需要使用不同的数据结构.

最明显的想法是[IORef GameObject]从世界中获取并IO [GameObject]通过调用readIORef每个索引将其转换为a .但这样效率很低.

我发现这样做的另一种可能方法是使用Data.Vector.MVectorand Data.Vector.Generic.unsafeUnfreezeunsafeFreeze,它们具有O(1)性能worldEntities :: !(MVector (PrimState IO) GameObject).问题是,unsafeUnfreezeunsafeFreeze对某些数据类型唯一的工作.

我也发现IOArray,所以我可以使用IOArray Int GameObject,但我找不到将IOArrays转换为不可变结构的方法.

最后,我可以做IORef [GameObject]或者IORef (Vector GameObject),但我不确定这会有多高效.

最有效的方法是什么?

mis*_*bee 5

您可以使用镜头而不是可变对象来获得"类似setter"的行为.在搞乱可变状态之前尝试一下,这在Haskell中非常难看(故意丑陋,以阻止你这样做).

(编辑添加:"类似setter"语法.镜头"setters"仍然创建对"set"ted结果的新引用,因此你仍然需要对主循环进行排序以从setter返回的值中读取,你可以'当然,重新读取旧的(不可变的)引用以获取更新的值.)