File tree 4 files changed +37
-20
lines changed
4 files changed +37
-20
lines changed Original file line number Diff line number Diff line change @@ -586,18 +586,28 @@ mapArray' f a =
586
586
587
587
-- | Create an array from a list of a known length. If the length
588
588
-- 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.
589
598
arrayFromListN :: Int -> [a ] -> Array a
599
+ {-# INLINE arrayFromListN #-}
590
600
arrayFromListN n l =
591
601
createArray n (die " fromListN" " uninitialized element" ) $ \ sma ->
592
- let go ! ix [] = if ix == n
602
+ let z ix # = if I # ix # == n
593
603
then return ()
594
604
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
596
606
then do
597
- writeArray sma ix x
598
- go (ix+ 1 ) xs
607
+ writeArray sma ( I # ix # ) x
608
+ k (ix# +# 1 # )
599
609
else die " fromListN" " list length greater than specified size"
600
- in go 0 l
610
+ in foldr f z l 0 #
601
611
602
612
-- | Create an array from a list.
603
613
arrayFromList :: [a ] -> Array a
Original file line number Diff line number Diff line change @@ -378,17 +378,20 @@ byteArrayFromList xs = byteArrayFromListN (length xs) xs
378
378
379
379
-- | Create a 'ByteArray' from a list of a known length. If the length
380
380
-- of the list does not match the given length, this throws an exception.
381
+
382
+ -- See Note [fromListN] in Data.Primitive.Array
381
383
byteArrayFromListN :: forall a . Prim a => Int -> [a ] -> ByteArray
384
+ {-# INLINE byteArrayFromListN #-}
382
385
byteArrayFromListN n ys = createByteArray (n * sizeOfType @ a ) $ \ marr ->
383
- let go ! ix [] = if ix == n
386
+ let z ix # = if I # ix # == n
384
387
then return ()
385
388
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
387
390
then do
388
- writeByteArray marr ix x
389
- go (ix + 1 ) xs
391
+ writeByteArray marr ( I # ix # ) x
392
+ k (ix# +# 1 # )
390
393
else die " byteArrayFromListN" " list length greater than specified size"
391
- in go 0 ys
394
+ in foldr f z ys 0 #
392
395
393
396
unI# :: Int -> Int #
394
397
unI# (I # n# ) = n#
Original file line number Diff line number Diff line change @@ -234,17 +234,20 @@ primArrayFromList vs = primArrayFromListN (L.length vs) vs
234
234
235
235
-- | Create a 'PrimArray' from a list of a known length. If the length
236
236
-- of the list does not match the given length, this throws an exception.
237
+
238
+ -- See Note [fromListN] in Data.Primitive.Array
237
239
primArrayFromListN :: forall a . Prim a => Int -> [a ] -> PrimArray a
240
+ {-# INLINE primArrayFromListN #-}
238
241
primArrayFromListN len vs = createPrimArray len $ \ arr ->
239
- let go [] ! ix = if ix == len
242
+ let z ix # = if I # ix # == len
240
243
then return ()
241
244
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
243
246
then do
244
- writePrimArray arr ix a
245
- go as (ix + 1 )
247
+ writePrimArray arr ( I # ix # ) a
248
+ k (ix# +# 1 # )
246
249
else die " fromListN" " list length greater than specified size"
247
- in go vs 0
250
+ in foldr f z vs 0 #
248
251
249
252
-- | Convert a 'PrimArray' to a list.
250
253
{-# 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
924
924
-- | Create a 'SmallArray' from a list of a known length. If the length
925
925
-- of the list does not match the given length, this throws an exception.
926
926
smallArrayFromListN :: Int -> [a ] -> SmallArray a
927
+ {-# INLINE smallArrayFromListN #-}
927
928
smallArrayFromListN n l =
928
929
createSmallArray n
929
930
(die " smallArrayFromListN" " uninitialized element" ) $ \ sma ->
930
- let go ! ix [] = if ix == n
931
+ let z ix # = if I # ix # == n
931
932
then return ()
932
933
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
934
935
then do
935
- writeSmallArray sma ix x
936
- go (ix + 1 ) xs
936
+ writeSmallArray sma ( I # ix # ) x
937
+ k (ix# +# 1 # )
937
938
else die " smallArrayFromListN" " list length greater than specified size"
938
- in go 0 l
939
+ in foldr f z l 0 #
939
940
940
941
-- | Create a 'SmallArray' from a list.
941
942
smallArrayFromList :: [a ] -> SmallArray a
You can’t perform that action at this time.
0 commit comments