Chad.Scherrer: > Hi, > > I'd like to be able to do replicateM, but over a vector instead of a list. > Right now I'm doing this: > > import qualified Data.Vector.Generic as G > import qualified Data.Vector.Unboxed.Mutable as M > replicateM n action = do > mu <- M.unsafeNew n > let go !i | i < n = action >>= M.unsafeWrite mu i >> go (i+1) > | otherwise = G.unsafeFreeze mu > go 0 > > I thought it might be useful to express this in terms of the available > primitives, since this might fuse more easily, but I don't yet see a > way to do it. > > Is there a better (more elegant and/or faster) way to write this? >
The way you're writing it is fine and direct, but yes, I think the challenge is to have have monadic generators that will fuse. The direct style, I'd write as: import qualified Data.Vector.Generic as G import qualified Data.Vector.Generic.Mutable as M import qualified Data.Vector.Generic.New as N import qualified Data.Vector.Fusion.Stream.Monadic as S replicateM :: (G.Vector v a) => Int -> IO a -> IO (v a) replicateM n a = do v <- M.new n fill v 0 G.unsafeFreeze v where fill v i | i < n = do x <- a M.unsafeWrite v i x fill v (i+1) | otherwise = return () But that doesn't fuse, obviously. So it seems we should be able to do something like: -- Almost there: replicateS n a = {-unsafeFreeze-} (M.unstream (S.replicate n a)) Or use Data.Vector.Generic.New, but I couldn't get the monadic action to work out, ending up in a twisty maze of PrimMonads. Roman? Can we generate frozen arrays for monadic generators, and still fuse in the current New/Mutable/MStream architecture? -- Don _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe