什么时候`修改`复制矢量?

Mic*_*mza 13 performance haskell functional-programming vector immutability

来自https://hackage.haskell.org/package/vector-0.12.0.1/docs/Data-Vector.html#v:modify

对矢量应用破坏性操作.如果安全的话,操作将在适当的位置执行,否则将修改矢量的副本.

听起来它可能具有截然不同的性能特征,这取决于在适当的位置修改矢量是否被认为是"安全的".这激发了问题......

修改何时进行到位,何时复制向量?有没有办法通过使用类型系统来确保它将被修改到位?

Tho*_*son 11

修改调用具有以下重写规则的Data.Vector.Generic.modify调用clone:

"clone/new [Vector]" forall p.
  clone (new p) = p
Run Code Online (Sandbox Code Playgroud)

因此,当某些东西处于语法形式时,new p它就不会被复制.看来modify,slice,init,tail,take,drop,unstream,和clone在这里融合以及最主要的.这与支持矢量设计的流融合工作(深度潜水的google-able纸张)密切相关.

编辑:根据你的评论我会详细说明.只有表单中的语法new p才能避免复制.既然你可能没有写new自己,那么它只会出现在矢量包中内联使用函数的结果.纵观矢量1,看来我确定上述使用的功能new,因此应当允许modify以不可复制,如果事情是内联的,甚至当时大多数只有那些新奇保存,矢量仍不得不通过像被刚刚建造create,force,modify,或unstream.

例如,如果您有代码:

v = fromList [1..10]
g = modify f v
f = undefined
Run Code Online (Sandbox Code Playgroud)

然后v将内联并且向量处于表单中new p(因为fromList使用的unstreamnew),因此modify不必复制数组.

另一方面,考虑:

v = let v0 = fromList [1..10] in 
{-# NOINLINE v #-}
g = modify f v
Run Code Online (Sandbox Code Playgroud)

现在v没有明确内联 - 它也可能没有内联,因为它来自不同的模块或表达式是共享的.因此,没有语法 代码,modify f (new p)重写规则也不会触发.

少做作,考虑:

g = let v = fromList [1..10]
        t = v ! 4
        v2 = modify f v
    in t + (v2 ! 4)
Run Code Online (Sandbox Code Playgroud)

这是一个常见的模式,其中一个向量被读取和修改 - 它显然不能在读取之前修改,重写规则要么不会触发(因为没有new)或者你将不得不失去共享v.

1例如,请参阅此处了解"slice/new [Vector]"规则.