Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unstreamM fusion incredibly easy to break #208

Open
bgamari opened this issue Apr 12, 2018 · 1 comment
Open

unstreamM fusion incredibly easy to break #208

bgamari opened this issue Apr 12, 2018 · 1 comment

Comments

@bgamari
Copy link
Contributor

bgamari commented Apr 12, 2018

It turns out that Data.Vector.Generic.unstreamM will more-often-than-not fail to fuse. For evidence look no farther than the implementation:

unstreamM :: (Monad m, Vector v a) => MBundle m u a -> m (v a)
{-# INLINE_FUSED unstreamM #-}
unstreamM s = do
                xs <- MBundle.toList s
                return $ unstream $ Bundle.unsafeFromList (MBundle.size s) xs

unstreamPrimM :: (PrimMonad m, Vector v a) => MBundle m u a -> m (v a)
{-# INLINE_FUSED unstreamPrimM #-}
unstreamPrimM s = M.munstream s >>= unsafeFreeze

-- FIXME: the next two functions are only necessary for the specialisations
unstreamPrimM_IO :: Vector v a => MBundle IO u a -> IO (v a)
{-# INLINE unstreamPrimM_IO #-}
unstreamPrimM_IO = unstreamPrimM

unstreamPrimM_ST :: Vector v a => MBundle (ST s) u a -> ST s (v a)
{-# INLINE unstreamPrimM_ST #-}
unstreamPrimM_ST = unstreamPrimM

{-# RULES

"unstreamM[IO]" unstreamM = unstreamPrimM_IO
"unstreamM[ST]" unstreamM = unstreamPrimM_ST  #-}

Note how unstreamM bundle will materialise the stream contents as a list in all monads except IO and ST. This seems Very Bad, although I'm not sure what can really be done. In principle we could use unstreamPrimM for any PrimMonad, but this of course we can't know during simplification.

bgamari added a commit to bgamari/fcs-sim that referenced this issue Apr 12, 2018
The monad stack it uses prevents efficient use of vector's unstreamM due to
haskell/vector#208.
@treeowl
Copy link
Contributor

treeowl commented May 15, 2018

This looks very similar to the issue of traverseing arrays. haskell/primitive#146 shows a way to work around it for appropriate monad transformer stacks on ST and IO. It's also possible to work around for some well-behaved "pure" monads like Either e. I don't know of a more general solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants