在可变函数中获取不可变向量的类型

时间:2014-07-11 16:39:03

标签: haskell

我有一个简单的就地函数,我正在使用可变向量来实现。但是,该函数需要一个使用不可变向量最容易构造的向量。下面是一些演示基本结构的玩具代码(但可能无法编译):

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的代码也更加丑陋。

我正在寻找一个允许我

的解决方案
  1. 轻松定义myvec(如上所述)(我看不出任何方法可以使用可变向量干净地完成此操作)
  2. 使用可能的最具体的矢量类型:例如,一个解决方案是使myvec返回一个盒装矢量,它可以容纳任何r类型。但是,我们关注速度,因此如果f的输入是一个可变的未装箱的向量,myvec应该是一个可变的未装箱的向量或一个不可变的未装箱的向量。
  3. 我也试图避免从myvec传递main(已知不可变类型):我们有足够的信息在{{}中生成 {1}},因此不需要从f传递矢量(除了可能的类型信息)。

1 个答案:

答案 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