Consider the example:
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
In core on each iteration I see sequence of newByteArray#, copyByteArray#, readIntArray#, writeIntArray# and unsafeFreezeByteArray#. It definitely creates intermediate copies.
Documentation states:
Apply a destructive operation to a vector. The operation will be performed in place if it is safe to do so and will modify a copy of the vector otherwise.
It is implemented as
modify p = new . New.modify p . clone
And there is RULE
"clone/new [Vector]" forall p.
clone (new p) = p
From my (pretty limited) understanding, two successive modify should not create intermediate copies:
modify p2 . modify p1
=> new . New.modify p2 . clone . new . New.modify p1 . clone
=> new . New.modify p2 . New.modify p1 . clone
Why doesn't it work in the process function? I think it should:
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
How can I make it work?
I think it's the recursion that's stopping it.
There's nowhere in the source code that says modify immediately followed by modify. Each iteration of the function calls modify again, but that happens at run-time, not compile-time. I think that's the problem. If you were to manually write three modify calls in a line, they would fuse.
I can't think of a way to make this fuse automatically. You could of course manually call clone and new yourself, but I can't think of a way to get the compiler to do this for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With