Skip to content

Commit 68d58e2

Browse files
committed
Add fromArrayMonolithic
For GHC, this should let us create a sequence out of an array without having any stray pointers to the array in the sequence.
1 parent 55f65cd commit 68d58e2

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

Data/Sequence.hs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ module Data.Sequence (
6060
fromList, -- :: [a] -> Seq a
6161
fromFunction, -- :: Int -> (Int -> a) -> Seq a
6262
fromArray, -- :: Ix i => Array i a -> Seq a
63+
fromArrayMonolithic, -- :: Ix i => Array i a -> Seq a
6364
-- ** Repetition
6465
replicate, -- :: Int -> a -> Seq a
6566
replicateA, -- :: Applicative f => Int -> f a -> f (Seq a)
@@ -177,6 +178,9 @@ import Data.Data
177178
import Data.Array (Ix, Array)
178179
#ifdef __GLASGOW_HASKELL__
179180
import qualified GHC.Arr
181+
import qualified Data.Primitive.Array as PA
182+
import Data.STRef
183+
import Control.Monad.ST
180184
#endif
181185

182186
-- Coercion on GHC 7.8+
@@ -1643,6 +1647,7 @@ fromArray a = fromFunction (GHC.Arr.numElements a) (GHC.Arr.unsafeAt a)
16431647
fromArray a = fromList2 (Data.Array.rangeSize (Data.Array.bounds a)) (Data.Array.elems a)
16441648
#endif
16451649

1650+
16461651
-- Splitting
16471652

16481653
-- | /O(log(min(i,n-i)))/. The first @i@ elements of a sequence.
@@ -2335,14 +2340,38 @@ unstableSortBy cmp (Seq xs) =
23352340
toPQ cmp (\ (Elem x) -> PQueue x Nil) xs
23362341

23372342
-- | fromList2, given a list and its length, constructs a completely
2338-
-- balanced Seq whose elements are that list using the applicativeTree
2343+
-- balanced Seq whose elements are that list using the replicateA
23392344
-- generalization.
23402345
fromList2 :: Int -> [a] -> Seq a
23412346
fromList2 n = execState (replicateA n (State ht))
23422347
where
23432348
ht (x:xs) = (xs, x)
23442349
ht [] = error "fromList2: short list"
23452350

2351+
-- | /O(n)/. Create a sequence consisting of the elements of an 'Array'. With
2352+
-- GHC, the result of 'fromArrayMonolithic' is guaranteed not to retain any
2353+
-- references to the array, unless individual array entries contain such. To
2354+
-- accomplish this, it reads each entry out of the array before returning. With
2355+
-- other implementations, this is identical to 'fromArray'.
2356+
fromArrayMonolithic :: Ix i => Array i a -> Seq a
2357+
#ifdef __GLASGOW_HASKELL__
2358+
fromArrayMonolithic (GHC.Arr.Array _ _ len ar)
2359+
= runST (fromArrayMonolithicST (PA.Array ar))
2360+
where
2361+
{-# INLINE fromArrayMonolithicST #-}
2362+
fromArrayMonolithicST :: PA.Array a -> ST s (Seq a)
2363+
fromArrayMonolithicST a =
2364+
do
2365+
i <- newSTRef (0::Int)
2366+
replicateA len (do
2367+
i' <- readSTRef i
2368+
x <- PA.indexArrayM a i'
2369+
writeSTRef i (i'+1)
2370+
return x)
2371+
#else
2372+
fromArrayMonolithic = fromArray
2373+
#endif
2374+
23462375
-- | A 'PQueue' is a simple pairing heap.
23472376
data PQueue e = PQueue e (PQL e)
23482377
data PQL e = Nil | {-# UNPACK #-} !(PQueue e) :& PQL e

containers.cabal

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ Library
3434
build-depends: base >= 4.2 && < 5, array, deepseq >= 1.2 && < 1.5
3535
if impl(ghc>=6.10)
3636
build-depends: ghc-prim
37+
if impl(ghc)
38+
build-depends: primitive
3739

3840
ghc-options: -O2 -Wall
3941

@@ -208,6 +210,8 @@ Test-suite seq-properties
208210
cpp-options: -DTESTING
209211

210212
build-depends: base >= 4.2 && < 5, array, deepseq >= 1.2 && < 1.5, ghc-prim
213+
if impl(ghc)
214+
build-depends: primitive
211215
ghc-options: -O2
212216
include-dirs: include
213217
extensions: MagicHash, DeriveDataTypeable, StandaloneDeriving, Rank2Types

0 commit comments

Comments
 (0)