【问题标题】:Getting type of immutable vector in a mutable function在可变函数中获取不可变向量的类型
【发布时间】: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 的代码也更难看。

我正在寻找一种解决方案,让我能够

  1. 轻松定义myvec(如上定义)(我看不出有任何方法可以用可变向量干净地做到这一点)
  2. 尽可能使用最具体的向量类型:例如,一种解决方案是让myvec 返回一个装箱向量,该向量可以包含任何r 类型。但是,我们担心速度,所以如果f 的输入是一个可变的未装箱向量,myvec 应该是一个可变的未装箱向量或不可变的未装箱向量。
  3. 我还试图避免从main(已知不可变类型)传入myvec:我们有足够的信息在f 本地生成,所以没有必要从 main 传递向量(类型信息除外)。

【问题讨论】:

  • 不能传类型吗? f (undefined::Int) v'?或者是否有一些 GADT 可以用来代替 Vector 类的通用性?我不是这些事情的专家;只是猜测。
  • 我可以将不可变向量类型从main 传递到f(不确定您将使用undefined :: Int 去哪里),但是当我必须这样做时似乎很疯狂完全有效(虽然丑陋)的替代方法是将 myvec 写为可变函数。
  • 您希望myvec 生成的向量填充什么?如果它是不可变的,你需要在创建时知道。目前你已经让它生成了一个Int 索引的向量。
  • 我又在看这个,想知道你为什么不把解冻和冻结从main移到f。我可能是错的,但我想任何不需要的冻结/解冻对可能会被编译掉。

标签: haskell


【解决方案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 中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-18
    • 1970-01-01
    • 2020-12-08
    • 1970-01-01
    • 1970-01-01
    • 2011-12-24
    相关资源
    最近更新 更多