具有不可变壳的Haskell可变结构

时间:2013-11-14 15:29:50

标签: arrays haskell io monads space

我对Haskell很新,所以对任何帮助表示赞赏!

我正在使用IOArray来更新恒定空间中的随机元素。我有一个看起来像这样的包装器:

data W = W{ arr:: IO (IOArray Int Node), n :: Int, ... }

但是,我找不到更新arr的方法,以便在传递包装器而不执行wrappper{arr = x}之类的操作时可以看到它,这会浪费大量的GC时间。在测试中,结果太慢了。

有没有办法更新arr以便全局可见?谢谢!

1 个答案:

答案 0 :(得分:3)

以下是如何使用ST阵列的快速示例

import Data.Array.ST hiding (unsafeThaw) -- Deprecated
import Data.Array (Array)
import Data.Array.Unsafe (unsafeThaw) -- If you really really really need it

newtype W a = W {arr :: Array Integer a}

modifyW :: a -> W a -> W a
modifyW v (W arr) = W $ runSTArray $ do -- The double $ is on purpose, . doesn't
                                        -- play so well with Rank n types.
  a <- thaw arr -- Turn `arr` into something we can modify
  writeArray a 1 v -- modify it
  return a

这将确保计算是纯粹的,但不会在modifyW内复制数组,所有这些修改都是恒定时间。如果您无法承担任何复制费用,可以使用unsafeThaw。但这很好......不安全。它实际上会修改纯数组,所以你必须非常小心,不要在modifyW运行后尝试使用纯结构。由于懒惰的评估,这比听起来要难得多,所以我要提醒你不要这样做。

使用这种风格,你可以从纯粹的Array中读取,然后当你需要修改它时,你会在ST monad中运行,这样你就可以做出不纯净的东西,但不会让它们流血进入你的其他计划。