@@ -102,7 +102,7 @@ import Foreign.Storable (Storable(..))
102import Prelude hiding (length, foldr, read, unlines, splitAt)
102import Prelude hiding (length, foldr, read, unlines, splitAt)
103import Text.Read (readPrec, readListPrec, readListPrecDefault)
103import Text.Read (readPrec, readListPrec, readListPrecDefault)
105−import GHC.Base (Addr#, nullAddr#, realWorld#)
105+import GHC.Base (Addr#, nullAddr#, realWorld#, build)
106import GHC.Exts (IsList, IsString(..))
106import GHC.Exts (IsList, IsString(..))
107import GHC.ForeignPtr (ForeignPtr(..), newForeignPtr_)
107import GHC.ForeignPtr (ForeignPtr(..), newForeignPtr_)
108import GHC.IO (IO(IO), unsafePerformIO)
108import GHC.IO (IO(IO), unsafePerformIO)
@@ -738,12 +738,33 @@ fromStreamD m = runFold write m
738 runFold (Fold step begin done) = D.foldlMx' step begin done
738 runFold (Fold step begin done) = D.foldlMx' step begin done
741+-- Use foldr/build fusion to fuse with list consumers
742+-- This can be useful when using the IsList instance
743+{-# INLINE_LATE toListFB #-}
744+toListFB :: forall a b. Storable a => (a -> b -> b) -> b -> Array a -> b
745+toListFB c n Array{..} = go (unsafeForeignPtrToPtr aStart)
748+ go p | p == aEnd = n
750+ -- unsafeInlineIO allows us to run this in Identity monad for pure
751+ -- toList/foldr case which makes them much faster due to not
752+ -- accumulating the list and fusing better with the pure consumers.
754+ -- This should be safe as the array contents are guaranteed to be
755+ -- evaluated/written to before we peek at them.
756+ let !x = unsafeInlineIO $ do
758+ touchForeignPtr aStart
760+ in c x (go (p `plusPtr` (sizeOf (undefined :: a))))
741-- | Convert an 'Array' into a list.
762-- | Convert an 'Array' into a list.
743-- @since 0.7.0
764-- @since 0.7.0
744−{-# INLINABLE toList #-}
765+{-# INLINE toList #-}
745toList :: Storable a => Array a -> [a]
766toList :: Storable a => Array a -> [a]
746−toList = foldr (:) []
767+toList s = build (\c n -> toListFB c n s)
748instance (Show a, Storable a) => Show (Array a) where
769instance (Show a, Storable a) => Show (Array a) where
749 {-# INLINE showsPrec #-}
770 {-# INLINE showsPrec #-}