Data.Vector.modify在每次迭代时创建矢量副本

Yur*_*ras 7 optimization haskell vector

考虑这个例子:

import qualified Data.Vector.Unboxed as Vector
import Data.Vector.Unboxed (Vector)
import qualified Data.Vector.Unboxed.Mutable as MVector

process :: [Int] -> Vector Int -> Vector Int
process [] v = v
process (x:xs) v = process xs $ Vector.modify modify v
  where
  modify mv = do
    old <- MVector.read mv x
    MVector.write mv x (old + 1)

main :: IO ()
main = do
  print $ process [1, 1, 3, 1] $ Vector.replicate 10 0
Run Code Online (Sandbox Code Playgroud)

core每次迭代我看到的序列newByteArray#,copyByteArray#,readIntArray#,writeIntArray#unsafeFreezeByteArray#.它肯定会创建中间副本.

文件说明:

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

它被实现为

modify p = new . New.modify p . clone
Run Code Online (Sandbox Code Playgroud)

而且有 RULE

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

从我(非常有限)的理解,两个连续modify不应该创建中间副本:

modify p2 . modify p1
=> new . New.modify p2 . clone . new . New.modify p1 . clone
=> new . New.modify p2 . New.modify p1 . clone
Run Code Online (Sandbox Code Playgroud)

为什么它在process功能中不起作用?我认为它应该:

process [1, 2] v
=> process [2] $ Vector.modify modify v
=> process [] $ Vector.modify modify $ Vector.modify modify v
=> Vector.modify modify $ Vector.modify modify v
=> the same as above
Run Code Online (Sandbox Code Playgroud)

我怎样才能使它工作?

Mat*_*hid 5

我认为这是阻止它的递归.

源代码中没有任何地方modify紧随其后modify.函数的每次迭代modify再次调用,但这发生在运行时,而不是编译时.我认为这就是问题所在.如果你要modify在一行中手动写三个电话,它们就会融合.

我想不出能够自动制作这种保险丝的方法.你当然可以手动调用clonenew你自己的,但我不能想办法让编译器为你做这个.

  • 是的,RULE是一个句法的东西.如果它找到与RULE中的表达式匹配的表达式,则会触发.它看起来内联,所以它可以找到更多的东西,但它仍然需要在语法上找到它. (2认同)