我有一个简单的就地函数,我正在使用可变向量来实现。但是,该函数需要一个使用不可变向量最容易构造的向量。下面是一些演示基本结构的玩具代码(但可能无法编译):
import Data.Vector.Generic as V
import Data.Vector.Unboxed as U
myvec :: (Vector v r) => Int -> v r
myvec i = V.generate i id
f :: (MVector v r, PrimMonad m) => v (PrimState m) r -> m ()
f y = let v = myvec 10 -- what should the type of `v` be?
--the following doesn't work since the Mutable type family is not injective:
_ = return v `asTypeOf` unsafeFreeze y
in do ....
main = do
-- at the top level, I know the input can be unboxed
let v = U.generate 10 (+(1::Int))
v' <- thaw v
f v'
y <- freeze v'
print y
我认为f
无法确定v
的(有效)不可变矢量类型。我只是让myvec
生成一个多态可变向量类型,但即使对于上面的简单函数,myvec
的代码也更加丑陋。
我正在寻找一个允许我
的解决方案myvec
(如上所述)(我看不出任何方法可以使用可变向量干净地完成此操作)myvec
返回一个盒装矢量,它可以容纳任何r
类型。但是,我们关注速度,因此如果f
的输入是一个可变的未装箱的向量,myvec
应该是一个可变的未装箱的向量或一个不可变的未装箱的向量。myvec
传递main
(已知不可变类型):我们有足够的信息在{{}中生成值 {1}},因此不需要从f
传递矢量(除了可能的类型信息)。答案 0 :(得分:1)
经过一番挖掘后,我想出了如何编写一个可变的generate
函数:
import Data.Vector.Generic.Mutable as M
import Data.Vector.Fusion.Stream as S
import Control.Monad.Primitive
mutableGenerate :: (MVector v r, PrimMonad m) => Int -> (Int -> r) -> m (v (PrimState m) r)
mutableGenerate i f = M.unstream $ S.generate i f
这允许我生成多态可变载体,但是使用不可变向量的简明表示法。在我看来,这似乎是一个有用的功能,应该包含在Data.Vector.Generic.Mutable
。