来自https://hackage.haskell.org/package/vector-0.12.0.1/docs/Data-Vector.html#v:modify
对矢量应用破坏性操作。如果安全的话,操作将在适当的位置执行,否则将修改矢量的副本。
这听起来可能具有截然不同的性能特征,这取决于在适当的位置修改矢量是否被视为“安全”。这激发了问题......
何时进行修改,以及何时复制向量?是否有某种方法可以通过使用类型系统来确保将进行适当的修改?
答案 0 :(得分:11)
修改调用具有以下重写规则的Data.Vector.Generic.modify
的调用clone
:
"clone/new [Vector]" forall p.
clone (new p) = p
因此,当某些内容处于new p
的句法形式时,它不会被复制。它显示为modify
,slice
,init
,tail
,take
,drop
,unstream
和clone
是融合在这里的主要因素。这与流融合工作(用于深度潜水的谷歌能力论文)密切相关,这是支持矢量设计的基础。
编辑:根据你的评论我会详细说明。只有语法new p
形式的东西才能避免复制。由于您可能不是自己编写new
,因此它只会出现在向量包中内联使用函数的结果。查看向量1,我上面确定的函数似乎使用了new
,因此如果事情是内联的,那么modify
就不允许复制 只保留新颖性,矢量仍然需要通过create
,force
,modify
或unstream
之类的新构造。
例如,如果您有代码:
v = fromList [1..10]
g = modify f v
f = undefined
然后v
将被内联,而向量的格式为new p
(因为fromList
使用unstream
new
},因此{{1}不必复制数组。
另一方面,请考虑:
modify
现在v = let v0 = fromList [1..10] in
{-# NOINLINE v #-}
g = modify f v
没有显式内联 - 它也可能无法内联,因为它来自不同的模块或表达式是共享的。因此,没有代码语法 v
,并且重写规则不会触发。
不那么做作,请考虑:
modify f (new p)
这是一个常见的模式,其中向量被读取和修改 - 显然在读取之前无法修改,并且重写规则要么不会被激活(因为那里没有g = let v = fromList [1..10]
t = v ! 4
v2 = modify f v
in t + (v2 ! 4)
)或者你我将不得不失去new
的分享。