Skip to content

Commit 6ce774c

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 6ce774c

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

Data/Sequence.hs

Lines changed: 31 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,39 @@ 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, or with GHC before base 4.4.0, this is identical to
2356+
-- 'fromArray'.
2357+
fromArrayMonolithic :: Ix i => Array i a -> Seq a
2358+
#if defined(__GLASGOW_HASKELL__) && MIN_VERSION_base(4,4,0)
2359+
fromArrayMonolithic (GHC.Arr.Array _ _ len ar)
2360+
= runST (fromArrayMonolithicST (PA.Array ar))
2361+
where
2362+
{-# INLINE fromArrayMonolithicST #-}
2363+
fromArrayMonolithicST :: PA.Array a -> ST s (Seq a)
2364+
fromArrayMonolithicST a =
2365+
do
2366+
i <- newSTRef (0::Int)
2367+
replicateA len (do
2368+
i' <- readSTRef i
2369+
x <- PA.indexArrayM a i'
2370+
writeSTRef i (i'+1)
2371+
return x)
2372+
#else
2373+
fromArrayMonolithic = fromArray
2374+
#endif
2375+
23462376
-- | A 'PQueue' is a simple pairing heap.
23472377
data PQueue e = PQueue e (PQL e)
23482378
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)