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生成中,而写入的对象在新的生成中时,才会发生此错误,因此您不会用最简单的测试来触发它。