简体   繁体   中英

Getting type of immutable vector in a mutable function

I have a simple in-place function which I'm using mutable vectors to implement. However, this function needs a vector which is most easily constructed using an immutable vector. Below is some toy code demonstrating the basic structure (but probably does not compile):

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

I don't see any way for f to determine a (valid) immutable vector type for v . I would just make myvec generate a polymorphic mutable vector type, but even for the simple function above, the code for myvec is much uglier.

I'm looking for a solution that allows me to

  1. Easily define myvec (as defined above) (and I don't see any way to do this cleanly with mutable vectors)
  2. Uses the most specific vector type possible: for example, one solution would be to make myvec return a boxed vector, which can hold any r type. However, we are concerned about speed so if the input to f is a mutable unboxed vector, myvec should either be a mutable unboxed vector or a immutable unboxed vector.
  3. I'm also trying to avoid passing in myvec from main (where the immutable type is known): we have enough information to generate the values locally in f , so passing the vector from main isn't necessary (except possibly for type information).

After some digging around, I figured out how to write a mutable generate function:

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

This allows me to generate a polymorphic mutable vector, but with concise notation of an immutable vector. This seems to me like a useful function that should be included in Data.Vector.Generic.Mutable .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM