5

文档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)unsafeFreeze当我需要使用该 API 时使用将是完美的逃生舱口,只要我不让自己在路上遇到更多不愉快的副作用。

4

1 回答 1

8

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

于 2019-01-04T16:20:43.707 回答