@@ -17,7 +17,7 @@ module Data.Primitive.Array (
1717 Array (.. ), MutableArray (.. ),
1818
1919 newArray , readArray , writeArray , indexArray , indexArrayM ,
20- freezeArray , thawArray ,
20+ freezeArray , thawArray , runArray ,
2121 unsafeFreezeArray , unsafeThawArray , sameMutableArray ,
2222 copyArray , copyMutableArray ,
2323 cloneArray , cloneMutableArray ,
@@ -54,12 +54,18 @@ import Data.Traversable (Traversable(..))
5454import Data.Monoid
5555#endif
5656#if MIN_VERSION_base(4,9,0)
57+ import qualified GHC.ST as GHCST
5758import qualified Data.Foldable as F
5859import Data.Semigroup
5960#endif
6061#if MIN_VERSION_base(4,8,0)
6162import Data.Functor.Identity
6263#endif
64+ #if MIN_VERSION_base(4,10,0)
65+ import GHC.Exts (runRW #)
66+ #elif MIN_VERSION_base(4,9,0)
67+ import GHC.Base (runRW #)
68+ #endif
6369
6470import Text.ParserCombinators.ReadP
6571
@@ -278,16 +284,63 @@ emptyArray =
278284 runST $ newArray 0 (die " emptyArray" " impossible" ) >>= unsafeFreezeArray
279285{-# NOINLINE emptyArray #-}
280286
287+ #if !MIN_VERSION_base(4,9,0)
281288createArray
282289 :: Int
283290 -> a
284291 -> (forall s . MutableArray s a -> ST s () )
285292 -> Array a
286293createArray 0 _ _ = emptyArray
287- createArray n x f = runST $ do
288- ma <- newArray n x
289- f ma
290- unsafeFreezeArray ma
294+ createArray n x f = runArray $ do
295+ mary <- newArray n x
296+ f mary
297+ pure mary
298+
299+ runArray
300+ :: (forall s . ST s (MutableArray s a ))
301+ -> Array a
302+ runArray m = runST $ m >>= unsafeFreezeArray
303+
304+ #else /* Below, runRW# is available. */
305+
306+ -- This low-level business is designed to work with GHC's worker-wrapper
307+ -- transformation. A lot of the time, we don't actually need an Array
308+ -- constructor. By putting it on the outside, and being careful about
309+ -- how we special-case the empty array, we can make GHC smarter about this.
310+ -- The only downside is that separately created 0-length arrays won't share
311+ -- their Array constructors, although they'll share their underlying
312+ -- Array#s.
313+ createArray
314+ :: Int
315+ -> a
316+ -> (forall s . MutableArray s a -> ST s () )
317+ -> Array a
318+ createArray 0 _ _ = Array (emptyArray# (# # ))
319+ createArray n x f = runArray $ do
320+ mary <- newArray n x
321+ f mary
322+ pure mary
323+
324+ runArray
325+ :: (forall s . ST s (MutableArray s a ))
326+ -> Array a
327+ runArray m = Array (runArray# m)
328+
329+ runArray#
330+ :: (forall s . ST s (MutableArray s a ))
331+ -> Array # a
332+ runArray# m = case runRW# $ \ s ->
333+ case unST m s of { (# s', MutableArray mary# # ) ->
334+ unsafeFreezeArray# mary# s'} of (# _, ary# # ) -> ary#
335+
336+ unST :: ST s a -> State # s -> (# State # s , a # )
337+ unST (GHCST. ST f) = f
338+
339+ emptyArray# :: (# # ) -> Array # a
340+ emptyArray# _ = case emptyArray of Array ar -> ar
341+ {-# NOINLINE emptyArray# #-}
342+ #endif
343+
291344
292345die :: String -> String -> a
293346die fun problem = error $ " Data.Primitive.Array." ++ fun ++ " : " ++ problem
@@ -507,18 +560,17 @@ unsafeTraverseArray f = \ !ary ->
507560{-# INLINE unsafeTraverseArray #-}
508561
509562arrayFromListN :: Int -> [a ] -> Array a
510- arrayFromListN n l = runST $ do
511- sma <- newArray n (die " fromListN" " uninitialized element" )
512- let go ! ix [] = if ix == n
513- then return ()
514- else die " fromListN" " list length less than specified size"
515- go ! ix (x : xs) = if ix < n
516- then do
517- writeArray sma ix x
518- go (ix+ 1 ) xs
519- else die " fromListN" " list length greater than specified size"
520- go 0 l
521- unsafeFreezeArray sma
563+ arrayFromListN n l =
564+ createArray n (die " fromListN" " uninitialized element" ) $ \ sma ->
565+ let go ! ix [] = if ix == n
566+ then return ()
567+ else die " fromListN" " list length less than specified size"
568+ go ! ix (x : xs) = if ix < n
569+ then do
570+ writeArray sma ix x
571+ go (ix+ 1 ) xs
572+ else die " fromListN" " list length greater than specified size"
573+ in go 0 l
522574
523575arrayFromList :: [a ] -> Array a
524576arrayFromList l = arrayFromListN (length l) l
@@ -547,13 +599,12 @@ instance Functor Array where
547599 writeArray mb i (f x) >> go (i+ 1 )
548600 in go 0
549601#if MIN_VERSION_base(4,8,0)
550- e <$ a = runST $ newArray (sizeofArray a) e >>= unsafeFreezeArray
602+ e <$ a = createArray (sizeofArray a) e ( \ ! _ -> pure () )
551603#endif
552604
553605instance Applicative Array where
554- pure x = runST $ newArray 1 x >>= unsafeFreezeArray
555- ab <*> a = runST $ do
556- mb <- newArray (szab* sza) $ die " <*>" " impossible"
606+ pure x = runArray $ newArray 1 x
607+ ab <*> a = createArray (szab* sza) (die " <*>" " impossible" ) $ \ mb ->
557608 let go1 i = when (i < szab) $
558609 do
559610 f <- indexArrayM ab i
@@ -564,8 +615,7 @@ instance Applicative Array where
564615 x <- indexArrayM a j
565616 writeArray mb (off + j) (f x)
566617 go2 off f (j + 1 )
567- go1 0
568- unsafeFreezeArray mb
618+ in go1 0
569619 where szab = sizeofArray ab ; sza = sizeofArray a
570620 a *> b = createArray (sza* szb) (die " *>" " impossible" ) $ \ mb ->
571621 let go i | i < sza = copyArray mb (i * szb) b 0 szb
0 commit comments