File tree Expand file tree Collapse file tree 4 files changed +37
-20
lines changed Expand file tree Collapse file tree 4 files changed +37
-20
lines changed Original file line number Diff line number Diff line change @@ -586,18 +586,28 @@ mapArray' f a =
586586
587587-- | Create an array from a list of a known length. If the length
588588-- of the list does not match the given length, this throws an exception.
589+
590+ -- Note [fromListN]
591+ -- ~~~~~~~~~~~~~~~~
592+ -- We want arrayFromListN to be a "good consumer" in list fusion, so we define
593+ -- the function using foldr and inline it to help fire fusion rules.
594+ -- If fusion occurs with a "good producer", it may reduce to a fold on some
595+ -- structure. In certain cases (such as for Data.Set) GHC is not be able to
596+ -- optimize the index to an unboxed Int# (see GHC #24628), so we explicitly use
597+ -- an Int# here.
589598arrayFromListN :: Int -> [a ] -> Array a
599+ {-# INLINE arrayFromListN #-}
590600arrayFromListN n l =
591601 createArray n (die " fromListN" " uninitialized element" ) $ \ sma ->
592- let go ! ix [] = if ix == n
602+ let z ix # = if I # ix # == n
593603 then return ()
594604 else die " fromListN" " list length less than specified size"
595- go ! ix (x : xs) = if ix < n
605+ f x k = GHC.Exts. oneShot $ \ ix # -> if I # ix # < n
596606 then do
597- writeArray sma ix x
598- go (ix+ 1 ) xs
607+ writeArray sma ( I # ix # ) x
608+ k (ix# +# 1 # )
599609 else die " fromListN" " list length greater than specified size"
600- in go 0 l
610+ in foldr f z l 0 #
601611
602612-- | Create an array from a list.
603613arrayFromList :: [a ] -> Array a
Original file line number Diff line number Diff line change @@ -378,17 +378,20 @@ byteArrayFromList xs = byteArrayFromListN (length xs) xs
378378
379379-- | Create a 'ByteArray' from a list of a known length. If the length
380380-- of the list does not match the given length, this throws an exception.
381+
382+ -- See Note [fromListN] in Data.Primitive.Array
381383byteArrayFromListN :: forall a . Prim a => Int -> [a ] -> ByteArray
384+ {-# INLINE byteArrayFromListN #-}
382385byteArrayFromListN n ys = createByteArray (n * sizeOfType @ a ) $ \ marr ->
383- let go ! ix [] = if ix == n
386+ let z ix # = if I # ix # == n
384387 then return ()
385388 else die " byteArrayFromListN" " list length less than specified size"
386- go ! ix (x : xs) = if ix < n
389+ f x k = GHC.Exts. oneShot $ \ ix # -> if I # ix # < n
387390 then do
388- writeByteArray marr ix x
389- go (ix + 1 ) xs
391+ writeByteArray marr ( I # ix # ) x
392+ k (ix# +# 1 # )
390393 else die " byteArrayFromListN" " list length greater than specified size"
391- in go 0 ys
394+ in foldr f z ys 0 #
392395
393396unI# :: Int -> Int #
394397unI# (I # n# ) = n#
Original file line number Diff line number Diff line change @@ -234,17 +234,20 @@ primArrayFromList vs = primArrayFromListN (L.length vs) vs
234234
235235-- | Create a 'PrimArray' from a list of a known length. If the length
236236-- of the list does not match the given length, this throws an exception.
237+
238+ -- See Note [fromListN] in Data.Primitive.Array
237239primArrayFromListN :: forall a . Prim a => Int -> [a ] -> PrimArray a
240+ {-# INLINE primArrayFromListN #-}
238241primArrayFromListN len vs = createPrimArray len $ \ arr ->
239- let go [] ! ix = if ix == len
242+ let z ix # = if I # ix # == len
240243 then return ()
241244 else die " fromListN" " list length less than specified size"
242- go (a : as) ! ix = if ix < len
245+ f a k = GHC.Exts. oneShot $ \ ix # -> if I # ix # < len
243246 then do
244- writePrimArray arr ix a
245- go as (ix + 1 )
247+ writePrimArray arr ( I # ix # ) a
248+ k (ix# +# 1 # )
246249 else die " fromListN" " list length greater than specified size"
247- in go vs 0
250+ in foldr f z vs 0 #
248251
249252-- | Convert a 'PrimArray' to a list.
250253{-# INLINE primArrayToList #-}
Original file line number Diff line number Diff line change @@ -924,18 +924,19 @@ instance (Typeable s, Typeable a) => Data (SmallMutableArray s a) where
924924-- | Create a 'SmallArray' from a list of a known length. If the length
925925-- of the list does not match the given length, this throws an exception.
926926smallArrayFromListN :: Int -> [a ] -> SmallArray a
927+ {-# INLINE smallArrayFromListN #-}
927928smallArrayFromListN n l =
928929 createSmallArray n
929930 (die " smallArrayFromListN" " uninitialized element" ) $ \ sma ->
930- let go ! ix [] = if ix == n
931+ let z ix # = if I # ix # == n
931932 then return ()
932933 else die " smallArrayFromListN" " list length less than specified size"
933- go ! ix (x : xs) = if ix < n
934+ f x k = GHC.Exts. oneShot $ \ ix # -> if I # ix # < n
934935 then do
935- writeSmallArray sma ix x
936- go (ix + 1 ) xs
936+ writeSmallArray sma ( I # ix # ) x
937+ k (ix# +# 1 # )
937938 else die " smallArrayFromListN" " list length greater than specified size"
938- in go 0 l
939+ in foldr f z l 0 #
939940
940941-- | Create a 'SmallArray' from a list.
941942smallArrayFromList :: [a ] -> SmallArray a
You can’t perform that action at this time.
0 commit comments