【发布时间】:2014-07-11 16:39:03
【问题描述】:
我有一个简单的就地函数,我使用可变向量来实现。但是,此函数需要一个最容易使用不可变向量构造的向量。下面是一些演示基本结构的玩具代码(但可能无法编译):
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应该是一个可变的未装箱向量或不可变的未装箱向量。 - 我还试图避免从
main(已知不可变类型)传入myvec:我们有足够的信息在f本地生成值,所以没有必要从main传递向量(类型信息除外)。
【问题讨论】:
-
不能传类型吗?
f (undefined::Int) v'?或者是否有一些 GADT 可以用来代替Vector类的通用性?我不是这些事情的专家;只是猜测。 -
我可以将不可变向量类型从
main传递到f(不确定您将使用undefined :: Int去哪里),但是当我必须这样做时似乎很疯狂完全有效(虽然丑陋)的替代方法是将myvec写为可变函数。 -
您希望
myvec生成的向量填充什么?如果它是不可变的,你需要在创建时知道。目前你已经让它生成了一个Int索引的向量。 -
我又在看这个,想知道你为什么不把解冻和冻结从
main移到f。我可能是错的,但我想任何不需要的冻结/解冻对可能会被编译掉。
标签: haskell