Haskell Data.Vector.modify在每次迭代中创建向量副本
举个例子:Haskell Data.Vector.modify在每次迭代中创建向量副本,haskell,optimization,vector,Haskell,Optimization,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 $ Vect
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
还有规则
"clone/new [Vector]" forall p.
clone (new p) = p
根据我(相当有限)的理解,连续两次modify
不应创建中间副本:
modify p2 . modify p1
=> new . New.modify p2 . clone . new . New.modify p1 . clone
=> new . New.modify p2 . New.modify p1 . clone
为什么它在过程中不起作用?我认为应该:
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
我怎样才能使它工作呢?我认为是递归阻止了它
源代码中没有一个地方会说modify
,后面紧跟着modify
。函数的每次迭代都会再次调用modify
,但这发生在运行时,而不是编译时。我想这就是问题所在。如果您要在一行中手动编写三个modify
调用,它们会融合
我想不出一个办法来自动熔断。当然,您可以自己手动调用clone
和new
,但我想不出一种方法让编译器为您执行此操作。为什么不生成一个调用modify
import Control.Monad (forM_)
[...]
process :: [Int] -> Vector Int -> Vector Int
process xs v = Vector.modify modify v
where
modify mv = forM_ xs $ \ x -> do
old <- MVector.read mv x
MVector.write mv x (old + 1)
import-Control.Monad(表单)
[...]
进程::[Int]->Vector Int->Vector Int
进程xs v=Vector.modify v
哪里
修改mv=forM_xs$\x->do
老啊,递归阻止内联,所以规则不会触发。对吗?是的,规则是一种句法上的东西。如果它找到与规则中的表达式匹配的表达式,则会激发。它关注内联,所以它可以找到更多的东西,但它仍然需要在语法上找到它,因为我已经有了折叠数据的纯函数(实际上它不是一个列表)。我可以实现一元版本,但在此之前,我想知道为什么不能重用现有版本。@Yuras我恐怕不理解你的评论。过程
函数基本上是一个foldl(Vector.modify…
)。我使用的是自定义数据类型,不是列表,但想法是一样的。对于我的数据类型,我的函数类似于foldl
,但还没有用于foldM
的模拟函数。而且它不是可遍历的实例,所以我不能使用表单
import Control.Monad (forM_)
[...]
process :: [Int] -> Vector Int -> Vector Int
process xs v = Vector.modify modify v
where
modify mv = forM_ xs $ \ x -> do
old <- MVector.read mv x
MVector.write mv x (old + 1)