Data.Vector的不安全冻结/不安全解冻有多"unsafe"?



Data.Vector.unsafeFreeze的文档中写道:

Unsafe[ly]在不复制的情况下将可变向量转换为不可变向量。此操作之后不能使用可变向量。

我想准确地描述"不安全"在这里的含义。在实验上,它似乎"仅"意味着对原始可变向量的进一步修改将导致unsafeFreeze返回的不可变向量不再是纯的:

$ import qualified Data.Vector as V
$ import qualified Data.Vector.Mutable as MV
$ import Control.Monad.ST
$ :{
$ |runST $ do
$ |        mv <- V.thaw $ V.fromList [0..10]
$ |        v <- V.unsafeFreeze mv
$ |        MV.write mv 0 (-1)
$ |        MV.write mv 1 (-2)
$ |        v' <- V.freeze mv
$ |        v'' <- V.unsafeFreeze mv
$ |        return (v, v', v'')
$ |:}
([-1,-2,2,3,4,5,6,7,8,9,10],[-1,-2,2,3,4,5,6,7,8,9,10],[-1,-2,2,3,4,5,6,7,8,9,10])

我可以想象,修改"不安全"冻结中使用的源会做各种棘手的事情,导致更糟糕的行为,例如分段。不幸的是,我很快就无法深入了解有关不安全操作的消息来源。

我能相信上述杂质是这些操作"不安全"的唯一方式吗?

对于上下文:我需要在一个典型的不可变数据结构上实现各种修改算法,而不在内部可变的范围内重用其公开的API将是非常不方便的(因为AFAICT没有办法通用地访问可变和不可变向量)。(Ab)当我需要使用API时,使用unsafeFreeze将是完美的逃生通道,只要我不会让自己在路上产生更多不愉快的副作用。

此使用模式可能崩溃:请参阅此消息以供参考。原因是,对一个不可变数组进行突变可以创建次要GC根,而这些根实际上对次要GC不可见。只有当您的数组在旧的GC生成中,而写入的对象在新的生成中时,才会发生此错误,因此您不会用最简单的测试来触发它。

最新更新