我对 Haskell 还很陌生,因此感谢您的帮助!
我正在使用 IOArray 来更新恒定空间中的随机元素。我有一个看起来像这样的包装器:
data W = W{ arr:: IO (IOArray Int Node), n :: Int, ... }
但是,我找不到更新的方法,arr
以便在传递包装器时不做类似的事情就可以看到它wrappper{arr = x}
,这会浪费大量的 GC 时间。在测试中,它变得太慢了。
有什么方法可以更新arr
以使其在全球范围内可见吗?谢谢!
这是一个如何使用 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
运行后尝试使用纯结构。由于惰性评估,这比听起来要困难得多,所以我会提醒你不要这样做。
使用这种风格,你从 pure 中读取Array
,然后当你需要修改它时,你在ST
monad 中运行,这让你做不纯的事情,但不会让它们渗入你的程序的其余部分。