Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting type of immutable vector in a mutable function

Tags:

haskell

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).
like image 614
crockeea Avatar asked Apr 19 '26 07:04

crockeea


1 Answers

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.

like image 95
crockeea Avatar answered Apr 21 '26 08:04

crockeea