{-# LANGUAGE CPP #-} #if __GLASGOW_HASKELL__ {-# LANGUAGE DeriveDataTypeable, StandaloneDeriving #-} #endif #if __GLASGOW_HASKELL__ >= 703 {-# LANGUAGE Trustworthy #-} #endif ----------------------------------------------------------------------------- -- | -- Module : Data.Sequence -- Copyright : (c) Ross Paterson 2005 -- (c) Louis Wasserman 2009 -- License : BSD-style -- Maintainer : libraries@haskell.org -- Stability : experimental -- Portability : portable -- -- General purpose finite sequences. -- Apart from being finite and having strict operations, sequences -- also differ from lists in supporting a wider variety of operations -- efficiently. -- -- An amortized running time is given for each operation, with /n/ referring -- to the length of the sequence and /i/ being the integral index used by -- some operations. These bounds hold even in a persistent (shared) setting. -- -- The implementation uses 2-3 finger trees annotated with sizes, -- as described in section 4.2 of -- -- * Ralf Hinze and Ross Paterson, -- \"Finger trees: a simple general-purpose data structure\", -- /Journal of Functional Programming/ 16:2 (2006) pp 197-217. -- -- -- /Note/: Many of these operations have the same names as similar -- operations on lists in the "Prelude". The ambiguity may be resolved -- using either qualification or the @hiding@ clause. -- ----------------------------------------------------------------------------- module Data.Sequence ( #if !defined(TESTING) Seq, #else Seq(..), Elem(..), FingerTree(..), Node(..), Digit(..), #endif -- * Construction empty, -- :: Seq a singleton, -- :: a -> Seq a (<|), -- :: a -> Seq a -> Seq a (|>), -- :: Seq a -> a -> Seq a (><), -- :: Seq a -> Seq a -> Seq a fromList, -- :: [a] -> Seq a -- ** Repetition replicate, -- :: Int -> a -> Seq a replicateA, -- :: Applicative f => Int -> f a -> f (Seq a) replicateM, -- :: Monad m => Int -> m a -> m (Seq a) -- ** Iterative construction iterateN, -- :: Int -> (a -> a) -> a -> Seq a unfoldr, -- :: (b -> Maybe (a, b)) -> b -> Seq a unfoldl, -- :: (b -> Maybe (b, a)) -> b -> Seq a -- * Deconstruction -- | Additional functions for deconstructing sequences are available -- via the 'Foldable' instance of 'Seq'. -- ** Queries null, -- :: Seq a -> Bool length, -- :: Seq a -> Int -- ** Views ViewL(..), viewl, -- :: Seq a -> ViewL a ViewR(..), viewr, -- :: Seq a -> ViewR a -- * Scans scanl, -- :: (a -> b -> a) -> a -> Seq b -> Seq a scanl1, -- :: (a -> a -> a) -> Seq a -> Seq a scanr, -- :: (a -> b -> b) -> b -> Seq a -> Seq b scanr1, -- :: (a -> a -> a) -> Seq a -> Seq a -- * Sublists tails, -- :: Seq a -> Seq (Seq a) inits, -- :: Seq a -> Seq (Seq a) -- ** Sequential searches takeWhileL, -- :: (a -> Bool) -> Seq a -> Seq a takeWhileR, -- :: (a -> Bool) -> Seq a -> Seq a dropWhileL, -- :: (a -> Bool) -> Seq a -> Seq a dropWhileR, -- :: (a -> Bool) -> Seq a -> Seq a spanl, -- :: (a -> Bool) -> Seq a -> (Seq a, Seq a) spanr, -- :: (a -> Bool) -> Seq a -> (Seq a, Seq a) breakl, -- :: (a -> Bool) -> Seq a -> (Seq a, Seq a) breakr, -- :: (a -> Bool) -> Seq a -> (Seq a, Seq a) partition, -- :: (a -> Bool) -> Seq a -> (Seq a, Seq a) filter, -- :: (a -> Bool) -> Seq a -> Seq a -- * Sorting sort, -- :: Ord a => Seq a -> Seq a sortBy, -- :: (a -> a -> Ordering) -> Seq a -> Seq a unstableSort, -- :: Ord a => Seq a -> Seq a unstableSortBy, -- :: (a -> a -> Ordering) -> Seq a -> Seq a -- * Indexing index, -- :: Seq a -> Int -> a adjust, -- :: (a -> a) -> Int -> Seq a -> Seq a update, -- :: Int -> a -> Seq a -> Seq a take, -- :: Int -> Seq a -> Seq a drop, -- :: Int -> Seq a -> Seq a splitAt, -- :: Int -> Seq a -> (Seq a, Seq a) -- ** Indexing with predicates -- | These functions perform sequential searches from the left -- or right ends of the sequence, returning indices of matching -- elements. elemIndexL, -- :: Eq a => a -> Seq a -> Maybe Int elemIndicesL, -- :: Eq a => a -> Seq a -> [Int] elemIndexR, -- :: Eq a => a -> Seq a -> Maybe Int elemIndicesR, -- :: Eq a => a -> Seq a -> [Int] findIndexL, -- :: (a -> Bool) -> Seq a -> Maybe Int findIndicesL, -- :: (a -> Bool) -> Seq a -> [Int] findIndexR, -- :: (a -> Bool) -> Seq a -> Maybe Int findIndicesR, -- :: (a -> Bool) -> Seq a -> [Int] -- * Folds -- | General folds are available via the 'Foldable' instance of 'Seq'. foldlWithIndex, -- :: (b -> Int -> a -> b) -> b -> Seq a -> b foldrWithIndex, -- :: (Int -> a -> b -> b) -> b -> Seq a -> b -- * Transformations mapWithIndex, -- :: (Int -> a -> b) -> Seq a -> Seq b reverse, -- :: Seq a -> Seq a -- ** Zips zip, -- :: Seq a -> Seq b -> Seq (a, b) zipWith, -- :: (a -> b -> c) -> Seq a -> Seq b -> Seq c zip3, -- :: Seq a -> Seq b -> Seq c -> Seq (a, b, c) zipWith3, -- :: (a -> b -> c -> d) -> Seq a -> Seq b -> Seq c -> Seq d zip4, -- :: Seq a -> Seq b -> Seq c -> Seq d -> Seq (a, b, c, d) zipWith4, -- :: (a -> b -> c -> d -> e) -> Seq a -> Seq b -> Seq c -> Seq d -> Seq e #if TESTING Sized(..), deep, node2, node3, #endif ) where import Prelude hiding ( Functor(..), null, length, take, drop, splitAt, foldl, foldl1, foldr, foldr1, scanl, scanl1, scanr, scanr1, replicate, zip, zipWith, zip3, zipWith3, takeWhile, dropWhile, iterate, reverse, filter, mapM, sum, all) import qualified Data.List import Control.Applicative (Applicative(..), (<$>), Alternative, WrappedMonad(..), liftA, liftA2, liftA3) import qualified Control.Applicative as Applicative (Alternative(..)) import Control.DeepSeq (NFData(rnf)) import Control.Monad (MonadPlus(..), ap) import Data.Monoid (Monoid(..)) import Data.Functor (Functor(..)) import Data.Foldable import Data.Traversable import Data.Typeable #ifdef __GLASGOW_HASKELL__ import GHC.Exts (build) import Text.Read (Lexeme(Ident), lexP, parens, prec, readPrec, readListPrec, readListPrecDefault) import Data.Data #endif infixr 5 `consTree` infixl 5 `snocTree` infixr 5 >< infixr 5 <|, :< infixl 5 |>, :> class Sized a where size :: a -> Int -- | General-purpose finite sequences. newtype Seq a = Seq (FingerTree (Elem a)) instance Functor Seq where fmap f (Seq xs) = Seq (fmap (fmap f) xs) #ifdef __GLASGOW_HASKELL__ x <$ s = replicate (length s) x #endif instance Foldable Seq where foldr f z (Seq xs) = foldr (flip (foldr f)) z xs foldl f z (Seq xs) = foldl (foldl f) z xs foldr1 f (Seq xs) = getElem (foldr1 f' xs) where f' (Elem x) (Elem y) = Elem (f x y) foldl1 f (Seq xs) = getElem (foldl1 f' xs) where f' (Elem x) (Elem y) = Elem (f x y) instance Traversable Seq where traverse f (Seq xs) = Seq <$> traverse (traverse f) xs instance NFData a => NFData (Seq a) where rnf (Seq xs) = rnf xs instance Monad Seq where return = singleton xs >>= f = foldl' add empty xs where add ys x = ys >< f x instance Applicative Seq where pure = singleton fs <*> xs = foldl' add empty fs where add ys f = ys >< fmap f xs instance MonadPlus Seq where mzero = empty mplus = (><) instance Alternative Seq where empty = empty (<|>) = (><) instance Eq a => Eq (Seq a) where xs == ys = length xs == length ys && toList xs == toList ys instance Ord a => Ord (Seq a) where compare xs ys = compare (toList xs) (toList ys) #if TESTING instance Show a => Show (Seq a) where showsPrec p (Seq x) = showsPrec p x #else instance Show a => Show (Seq a) where showsPrec p xs = showParen (p > 10) $ showString "fromList " . shows (toList xs) #endif instance Read a => Read (Seq a) where #ifdef __GLASGOW_HASKELL__ readPrec = parens $ prec 10 $ do Ident "fromList" <- lexP xs <- readPrec return (fromList xs) readListPrec = readListPrecDefault #else readsPrec p = readParen (p > 10) $ \ r -> do ("fromList",s) <- lex r (xs,t) <- reads s return (fromList xs,t) #endif instance Monoid (Seq a) where mempty = empty mappend = (><) #include "Typeable.h" INSTANCE_TYPEABLE1(Seq,seqTc,"Seq") #if __GLASGOW_HASKELL__ instance Data a => Data (Seq a) where gfoldl f z s = case viewl s of EmptyL -> z empty x :< xs -> z (<|) `f` x `f` xs gunfold k z c = case constrIndex c of 1 -> z empty 2 -> k (k (z (<|))) _ -> error "gunfold" toConstr xs | null xs = emptyConstr | otherwise = consConstr dataTypeOf _ = seqDataType dataCast1 f = gcast1 f emptyConstr, consConstr :: Constr emptyConstr = mkConstr seqDataType "empty" [] Prefix consConstr = mkConstr seqDataType "<|" [] Infix seqDataType :: DataType seqDataType = mkDataType "Data.Sequence.Seq" [emptyConstr, consConstr] #endif -- Finger trees data FingerTree a = Empty | Single a | Deep {-# UNPACK #-} !Int !(Digit a) (FingerTree (Node a)) !(Digit a) #if TESTING deriving Show #endif instance Sized a => Sized (FingerTree a) where {-# SPECIALIZE instance Sized (FingerTree (Elem a)) #-} {-# SPECIALIZE instance Sized (FingerTree (Node a)) #-} size Empty = 0 size (Single x) = size x size (Deep v _ _ _) = v instance Foldable FingerTree where foldr _ z Empty = z foldr f z (Single x) = x `f` z foldr f z (Deep _ pr m sf) = foldr f (foldr (flip (foldr f)) (foldr f z sf) m) pr foldl _ z Empty = z foldl f z (Single x) = z `f` x foldl f z (Deep _ pr m sf) = foldl f (foldl (foldl f) (foldl f z pr) m) sf foldr1 _ Empty = error "foldr1: empty sequence" foldr1 _ (Single x) = x foldr1 f (Deep _ pr m sf) = foldr f (foldr (flip (foldr f)) (foldr1 f sf) m) pr foldl1 _ Empty = error "foldl1: empty sequence" foldl1 _ (Single x) = x foldl1 f (Deep _ pr m sf) = foldl f (foldl (foldl f) (foldl1 f pr) m) sf instance Functor FingerTree where fmap _ Empty = Empty fmap f (Single x) = Single (f x) fmap f (Deep v pr m sf) = Deep v (fmap f pr) (fmap (fmap f) m) (fmap f sf) instance Traversable FingerTree where traverse _ Empty = pure Empty traverse f (Single x) = Single <$> f x traverse f (Deep v pr m sf) = Deep v <$> traverse f pr <*> traverse (traverse f) m <*> traverse f sf instance NFData a => NFData (FingerTree a) where rnf (Empty) = () rnf (Single x) = rnf x rnf (Deep _ pr m sf) = rnf pr `seq` rnf m `seq` rnf sf {-# INLINE deep #-} deep :: Sized a => Digit a -> FingerTree (Node a) -> Digit a -> FingerTree a deep pr m sf = Deep (size pr + size m + size sf) pr m sf {-# INLINE pullL #-} pullL :: Sized a => Int -> FingerTree (Node a) -> Digit a -> FingerTree a pullL s m sf = case viewLTree m of Nothing2 -> digitToTree' s sf Just2 pr m' -> Deep s (nodeToDigit pr) m' sf {-# INLINE pullR #-} pullR :: Sized a => Int -> Digit a -> FingerTree (Node a) -> FingerTree a pullR s pr m = case viewRTree m of Nothing2 -> digitToTree' s pr Just2 m' sf -> Deep s pr m' (nodeToDigit sf) {-# SPECIALIZE deepL :: Maybe (Digit (Elem a)) -> FingerTree (Node (Elem a)) -> Digit (Elem a) -> FingerTree (Elem a) #-} {-# SPECIALIZE deepL :: Maybe (Digit (Node a)) -> FingerTree (Node (Node a)) -> Digit (Node a) -> FingerTree (Node a) #-} deepL :: Sized a => Maybe (Digit a) -> FingerTree (Node a) -> Digit a -> FingerTree a deepL Nothing m sf = pullL (size m + size sf) m sf deepL (Just pr) m sf = deep pr m sf {-# SPECIALIZE deepR :: Digit (Elem a) -> FingerTree (Node (Elem a)) -> Maybe (Digit (Elem a)) -> FingerTree (Elem a) #-} {-# SPECIALIZE deepR :: Digit (Node a) -> FingerTree (Node (Node a)) -> Maybe (Digit (Node a)) -> FingerTree (Node a) #-} deepR :: Sized a => Digit a -> FingerTree (Node a) -> Maybe (Digit a) -> FingerTree a deepR pr m Nothing = pullR (size m + size pr) pr m deepR pr m (Just sf) = deep pr m sf -- Digits data Digit a = One a | Two a a | Three a a a | Four a a a a #if TESTING deriving Show #endif instance Foldable Digit where foldr f z (One a) = a `f` z foldr f z (Two a b) = a `f` (b `f` z) foldr f z (Three a b c) = a `f` (b `f` (c `f` z)) foldr f z (Four a b c d) = a `f` (b `f` (c `f` (d `f` z))) foldl f z (One a) = z `f` a foldl f z (Two a b) = (z `f` a) `f` b foldl f z (Three a b c) = ((z `f` a) `f` b) `f` c foldl f z (Four a b c d) = (((z `f` a) `f` b) `f` c) `f` d foldr1 _ (One a) = a foldr1 f (Two a b) = a `f` b foldr1 f (Three a b c) = a `f` (b `f` c) foldr1 f (Four a b c d) = a `f` (b `f` (c `f` d)) foldl1 _ (One a) = a foldl1 f (Two a b) = a `f` b foldl1 f (Three a b c) = (a `f` b) `f` c foldl1 f (Four a b c d) = ((a `f` b) `f` c) `f` d instance Functor Digit where {-# INLINE fmap #-} fmap f (One a) = One (f a) fmap f (Two a b) = Two (f a) (f b) fmap f (Three a b c) = Three (f a) (f b) (f c) fmap f (Four a b c d) = Four (f a) (f b) (f c) (f d) instance Traversable Digit where {-# INLINE traverse #-} traverse f (One a) = One <$> f a traverse f (Two a b) = Two <$> f a <*> f b traverse f (Three a b c) = Three <$> f a <*> f b <*> f c traverse f (Four a b c d) = Four <$> f a <*> f b <*> f c <*> f d instance NFData a => NFData (Digit a) where rnf (One a) = rnf a rnf (Two a b) = rnf a `seq` rnf b rnf (Three a b c) = rnf a `seq` rnf b `seq` rnf c rnf (Four a b c d) = rnf a `seq` rnf b `seq` rnf c `seq` rnf d instance Sized a => Sized (Digit a) where {-# INLINE size #-} size = foldl1 (+) . fmap size {-# SPECIALIZE digitToTree :: Digit (Elem a) -> FingerTree (Elem a) #-} {-# SPECIALIZE digitToTree :: Digit (Node a) -> FingerTree (Node a) #-} digitToTree :: Sized a => Digit a -> FingerTree a digitToTree (One a) = Single a digitToTree (Two a b) = deep (One a) Empty (One b) digitToTree (Three a b c) = deep (Two a b) Empty (One c) digitToTree (Four a b c d) = deep (Two a b) Empty (Two c d) -- | Given the size of a digit and the digit itself, efficiently converts -- it to a FingerTree. digitToTree' :: Int -> Digit a -> FingerTree a digitToTree' n (Four a b c d) = Deep n (Two a b) Empty (Two c d) digitToTree' n (Three a b c) = Deep n (Two a b) Empty (One c) digitToTree' n (Two a b) = Deep n (One a) Empty (One b) digitToTree' n (One a) = n `seq` Single a -- Nodes data Node a = Node2 {-# UNPACK #-} !Int a a | Node3 {-# UNPACK #-} !Int a a a #if TESTING deriving Show #endif instance Foldable Node where foldr f z (Node2 _ a b) = a `f` (b `f` z) foldr f z (Node3 _ a b c) = a `f` (b `f` (c `f` z)) foldl f z (Node2 _ a b) = (z `f` a) `f` b foldl f z (Node3 _ a b c) = ((z `f` a) `f` b) `f` c instance Functor Node where {-# INLINE fmap #-} fmap f (Node2 v a b) = Node2 v (f a) (f b) fmap f (Node3 v a b c) = Node3 v (f a) (f b) (f c) instance Traversable Node where {-# INLINE traverse #-} traverse f (Node2 v a b) = Node2 v <$> f a <*> f b traverse f (Node3 v a b c) = Node3 v <$> f a <*> f b <*> f c instance NFData a => NFData (Node a) where rnf (Node2 _ a b) = rnf a `seq` rnf b rnf (Node3 _ a b c) = rnf a `seq` rnf b `seq` rnf c instance Sized (Node a) where size (Node2 v _ _) = v size (Node3 v _ _ _) = v {-# INLINE node2 #-} node2 :: Sized a => a -> a -> Node a node2 a b = Node2 (size a + size b) a b {-# INLINE node3 #-} node3 :: Sized a => a -> a -> a -> Node a node3 a b c = Node3 (size a + size b + size c) a b c nodeToDigit :: Node a -> Digit a nodeToDigit (Node2 _ a b) = Two a b nodeToDigit (Node3 _ a b c) = Three a b c -- Elements newtype Elem a = Elem { getElem :: a } #if TESTING deriving Show #endif instance Sized (Elem a) where size _ = 1 instance Functor Elem where fmap f (Elem x) = Elem (f x) instance Foldable Elem where foldr f z (Elem x) = f x z foldl f z (Elem x) = f z x instance Traversable Elem where traverse f (Elem x) = Elem <$> f x instance NFData a => NFData (Elem a) where rnf (Elem x) = rnf x ------------------------------------------------------- -- Applicative construction ------------------------------------------------------- newtype Id a = Id {runId :: a} instance Functor Id where fmap f (Id x) = Id (f x) instance Monad Id where return = Id m >>= k = k (runId m) instance Applicative Id where pure = return (<*>) = ap -- | This is essentially a clone of Control.Monad.State.Strict. newtype State s a = State {runState :: s -> (s, a)} instance Functor (State s) where fmap = liftA instance Monad (State s) where {-# INLINE return #-} {-# INLINE (>>=) #-} return x = State $ \ s -> (s, x) m >>= k = State $ \ s -> case runState m s of (s', x) -> runState (k x) s' instance Applicative (State s) where pure = return (<*>) = ap execState :: State s a -> s -> a execState m x = snd (runState m x) -- | A helper method: a strict version of mapAccumL. mapAccumL' :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c) mapAccumL' f s t = runState (traverse (State . flip f) t) s -- | 'applicativeTree' takes an Applicative-wrapped construction of a -- piece of a FingerTree, assumed to always have the same size (which -- is put in the second argument), and replicates it as many times as -- specified. This is a generalization of 'replicateA', which itself -- is a generalization of many Data.Sequence methods. {-# SPECIALIZE applicativeTree :: Int -> Int -> State s a -> State s (FingerTree a) #-} {-# SPECIALIZE applicativeTree :: Int -> Int -> Id a -> Id (FingerTree a) #-} -- Special note: the Id specialization automatically does node sharing, -- reducing memory usage of the resulting tree to /O(log n)/. applicativeTree :: Applicative f => Int -> Int -> f a -> f (FingerTree a) applicativeTree n mSize m = mSize `seq` case n of 0 -> pure Empty 1 -> liftA Single m 2 -> deepA one emptyTree one 3 -> deepA two emptyTree one 4 -> deepA two emptyTree two 5 -> deepA three emptyTree two 6 -> deepA three emptyTree three 7 -> deepA four emptyTree three 8 -> deepA four emptyTree four _ -> let (q, r) = n `quotRem` 3 in q `seq` case r of 0 -> deepA three (applicativeTree (q - 2) mSize' n3) three 1 -> deepA four (applicativeTree (q - 2) mSize' n3) three _ -> deepA four (applicativeTree (q - 2) mSize' n3) four where one = liftA One m two = liftA2 Two m m three = liftA3 Three m m m four = liftA3 Four m m m <*> m deepA = liftA3 (Deep (n * mSize)) mSize' = 3 * mSize n3 = liftA3 (Node3 mSize') m m m emptyTree = pure Empty ------------------------------------------------------------------------ -- Construction ------------------------------------------------------------------------ -- | /O(1)/. The empty sequence. empty :: Seq a empty = Seq Empty -- | /O(1)/. A singleton sequence. singleton :: a -> Seq a singleton x = Seq (Single (Elem x)) -- | /O(log n)/. @replicate n x@ is a sequence consisting of @n@ copies of @x@. replicate :: Int -> a -> Seq a replicate n x | n >= 0 = runId (replicateA n (Id x)) | otherwise = error "replicate takes a nonnegative integer argument" -- | 'replicateA' is an 'Applicative' version of 'replicate', and makes -- /O(log n)/ calls to '<*>' and 'pure'. -- -- > replicateA n x = sequenceA (replicate n x) replicateA :: Applicative f => Int -> f a -> f (Seq a) replicateA n x | n >= 0 = Seq <$> applicativeTree n 1 (Elem <$> x) | otherwise = error "replicateA takes a nonnegative integer argument" -- | 'replicateM' is a sequence counterpart of 'Control.Monad.replicateM'. -- -- > replicateM n x = sequence (replicate n x) replicateM :: Monad m => Int -> m a -> m (Seq a) replicateM n x | n >= 0 = unwrapMonad (replicateA n (WrapMonad x)) | otherwise = error "replicateM takes a nonnegative integer argument" -- | /O(1)/. Add an element to the left end of a sequence. -- Mnemonic: a triangle with the single element at the pointy end. (<|) :: a -> Seq a -> Seq a x <| Seq xs = Seq (Elem x `consTree` xs) {-# SPECIALIZE consTree :: Elem a -> FingerTree (Elem a) -> FingerTree (Elem a) #-} {-# SPECIALIZE consTree :: Node a -> FingerTree (Node a) -> FingerTree (Node a) #-} consTree :: Sized a => a -> FingerTree a -> FingerTree a consTree a Empty = Single a consTree a (Single b) = deep (One a) Empty (One b) consTree a (Deep s (Four b c d e) m sf) = m `seq` Deep (size a + s) (Two a b) (node3 c d e `consTree` m) sf consTree a (Deep s (Three b c d) m sf) = Deep (size a + s) (Four a b c d) m sf consTree a (Deep s (Two b c) m sf) = Deep (size a + s) (Three a b c) m sf consTree a (Deep s (One b) m sf) = Deep (size a + s) (Two a b) m sf -- | /O(1)/. Add an element to the right end of a sequence. -- Mnemonic: a triangle with the single element at the pointy end. (|>) :: Seq a -> a -> Seq a Seq xs |> x = Seq (xs `snocTree` Elem x) {-# SPECIALIZE snocTree :: FingerTree (Elem a) -> Elem a -> FingerTree (Elem a) #-} {-# SPECIALIZE snocTree :: FingerTree (Node a) -> Node a -> FingerTree (Node a) #-} snocTree :: Sized a => FingerTree a -> a -> FingerTree a snocTree Empty a = Single a snocTree (Single a) b = deep (One a) Empty (One b) snocTree (Deep s pr m (Four a b c d)) e = m `seq` Deep (s + size e) pr (m `snocTree` node3 a b c) (Two d e) snocTree (Deep s pr m (Three a b c)) d = Deep (s + size d) pr m (Four a b c d) snocTree (Deep s pr m (Two a b)) c = Deep (s + size c) pr m (Three a b c) snocTree (Deep s pr m (One a)) b = Deep (s + size b) pr m (Two a b) -- | /O(log(min(n1,n2)))/. Concatenate two sequences. (><) :: Seq a -> Seq a -> Seq a Seq xs >< Seq ys = Seq (appendTree0 xs ys) -- The appendTree/addDigits gunk below is machine generated appendTree0 :: FingerTree (Elem a) -> FingerTree (Elem a) -> FingerTree (Elem a) appendTree0 Empty xs = xs appendTree0 xs Empty = xs appendTree0 (Single x) xs = x `consTree` xs appendTree0 xs (Single x) = xs `snocTree` x appendTree0 (Deep s1 pr1 m1 sf1) (Deep s2 pr2 m2 sf2) = Deep (s1 + s2) pr1 (addDigits0 m1 sf1 pr2 m2) sf2 addDigits0 :: FingerTree (Node (Elem a)) -> Digit (Elem a) -> Digit (Elem a) -> FingerTree (Node (Elem a)) -> FingerTree (Node (Elem a)) addDigits0 m1 (One a) (One b) m2 = appendTree1 m1 (node2 a b) m2 addDigits0 m1 (One a) (Two b c) m2 = appendTree1 m1 (node3 a b c) m2 addDigits0 m1 (One a) (Three b c d) m2 = appendTree2 m1 (node2 a b) (node2 c d) m2 addDigits0 m1 (One a) (Four b c d e) m2 = appendTree2 m1 (node3 a b c) (node2 d e) m2 addDigits0 m1 (Two a b) (One c) m2 = appendTree1 m1 (node3 a b c) m2 addDigits0 m1 (Two a b) (Two c d) m2 = appendTree2 m1 (node2 a b) (node2 c d) m2 addDigits0 m1 (Two a b) (Three c d e) m2 = appendTree2 m1 (node3 a b c) (node2 d e) m2 addDigits0 m1 (Two a b) (Four c d e f) m2 = appendTree2 m1 (node3 a b c) (node3 d e f) m2 addDigits0 m1 (Three a b c) (One d) m2 = appendTree2 m1 (node2 a b) (node2 c d) m2 addDigits0 m1 (Three a b c) (Two d e) m2 = appendTree2 m1 (node3 a b c) (node2 d e) m2 addDigits0 m1 (Three a b c) (Three d e f) m2 = appendTree2 m1 (node3 a b c) (node3 d e f) m2 addDigits0 m1 (Three a b c) (Four d e f g) m2 = appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2 addDigits0 m1 (Four a b c d) (One e) m2 = appendTree2 m1 (node3 a b c) (node2 d e) m2 addDigits0 m1 (Four a b c d) (Two e f) m2 = appendTree2 m1 (node3 a b c) (node3 d e f) m2 addDigits0 m1 (Four a b c d) (Three e f g) m2 = appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2 addDigits0 m1 (Four a b c d) (Four e f g h) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2 appendTree1 :: FingerTree (Node a) -> Node a -> FingerTree (Node a) -> FingerTree (Node a) appendTree1 Empty a xs = a `consTree` xs appendTree1 xs a Empty = xs `snocTree` a appendTree1 (Single x) a xs = x `consTree` a `consTree` xs appendTree1 xs a (Single x) = xs `snocTree` a `snocTree` x appendTree1 (Deep s1 pr1 m1 sf1) a (Deep s2 pr2 m2 sf2) = Deep (s1 + size a + s2) pr1 (addDigits1 m1 sf1 a pr2 m2) sf2 addDigits1 :: FingerTree (Node (Node a)) -> Digit (Node a) -> Node a -> Digit (Node a) -> FingerTree (Node (Node a)) -> FingerTree (Node (Node a)) addDigits1 m1 (One a) b (One c) m2 = appendTree1 m1 (node3 a b c) m2 addDigits1 m1 (One a) b (Two c d) m2 = appendTree2 m1 (node2 a b) (node2 c d) m2 addDigits1 m1 (One a) b (Three c d e) m2 = appendTree2 m1 (node3 a b c) (node2 d e) m2 addDigits1 m1 (One a) b (Four c d e f) m2 = appendTree2 m1 (node3 a b c) (node3 d e f) m2 addDigits1 m1 (Two a b) c (One d) m2 = appendTree2 m1 (node2 a b) (node2 c d) m2 addDigits1 m1 (Two a b) c (Two d e) m2 = appendTree2 m1 (node3 a b c) (node2 d e) m2 addDigits1 m1 (Two a b) c (Three d e f) m2 = appendTree2 m1 (node3 a b c) (node3 d e f) m2 addDigits1 m1 (Two a b) c (Four d e f g) m2 = appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2 addDigits1 m1 (Three a b c) d (One e) m2 = appendTree2 m1 (node3 a b c) (node2 d e) m2 addDigits1 m1 (Three a b c) d (Two e f) m2 = appendTree2 m1 (node3 a b c) (node3 d e f) m2 addDigits1 m1 (Three a b c) d (Three e f g) m2 = appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2 addDigits1 m1 (Three a b c) d (Four e f g h) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2 addDigits1 m1 (Four a b c d) e (One f) m2 = appendTree2 m1 (node3 a b c) (node3 d e f) m2 addDigits1 m1 (Four a b c d) e (Two f g) m2 = appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2 addDigits1 m1 (Four a b c d) e (Three f g h) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2 addDigits1 m1 (Four a b c d) e (Four f g h i) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2 appendTree2 :: FingerTree (Node a) -> Node a -> Node a -> FingerTree (Node a) -> FingerTree (Node a) appendTree2 Empty a b xs = a `consTree` b `consTree` xs appendTree2 xs a b Empty = xs `snocTree` a `snocTree` b appendTree2 (Single x) a b xs = x `consTree` a `consTree` b `consTree` xs appendTree2 xs a b (Single x) = xs `snocTree` a `snocTree` b `snocTree` x appendTree2 (Deep s1 pr1 m1 sf1) a b (Deep s2 pr2 m2 sf2) = Deep (s1 + size a + size b + s2) pr1 (addDigits2 m1 sf1 a b pr2 m2) sf2 addDigits2 :: FingerTree (Node (Node a)) -> Digit (Node a) -> Node a -> Node a -> Digit (Node a) -> FingerTree (Node (Node a)) -> FingerTree (Node (Node a)) addDigits2 m1 (One a) b c (One d) m2 = appendTree2 m1 (node2 a b) (node2 c d) m2 addDigits2 m1 (One a) b c (Two d e) m2 = appendTree2 m1 (node3 a b c) (node2 d e) m2 addDigits2 m1 (One a) b c (Three d e f) m2 = appendTree2 m1 (node3 a b c) (node3 d e f) m2 addDigits2 m1 (One a) b c (Four d e f g) m2 = appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2 addDigits2 m1 (Two a b) c d (One e) m2 = appendTree2 m1 (node3 a b c) (node2 d e) m2 addDigits2 m1 (Two a b) c d (Two e f) m2 = appendTree2 m1 (node3 a b c) (node3 d e f) m2 addDigits2 m1 (Two a b) c d (Three e f g) m2 = appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2 addDigits2 m1 (Two a b) c d (Four e f g h) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2 addDigits2 m1 (Three a b c) d e (One f) m2 = appendTree2 m1 (node3 a b c) (node3 d e f) m2 addDigits2 m1 (Three a b c) d e (Two f g) m2 = appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2 addDigits2 m1 (Three a b c) d e (Three f g h) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2 addDigits2 m1 (Three a b c) d e (Four f g h i) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2 addDigits2 m1 (Four a b c d) e f (One g) m2 = appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2 addDigits2 m1 (Four a b c d) e f (Two g h) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2 addDigits2 m1 (Four a b c d) e f (Three g h i) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2 addDigits2 m1 (Four a b c d) e f (Four g h i j) m2 = appendTree4 m1 (node3 a b c) (node3 d e f) (node2 g h) (node2 i j) m2 appendTree3 :: FingerTree (Node a) -> Node a -> Node a -> Node a -> FingerTree (Node a) -> FingerTree (Node a) appendTree3 Empty a b c xs = a `consTree` b `consTree` c `consTree` xs appendTree3 xs a b c Empty = xs `snocTree` a `snocTree` b `snocTree` c appendTree3 (Single x) a b c xs = x `consTree` a `consTree` b `consTree` c `consTree` xs appendTree3 xs a b c (Single x) = xs `snocTree` a `snocTree` b `snocTree` c `snocTree` x appendTree3 (Deep s1 pr1 m1 sf1) a b c (Deep s2 pr2 m2 sf2) = Deep (s1 + size a + size b + size c + s2) pr1 (addDigits3 m1 sf1 a b c pr2 m2) sf2 addDigits3 :: FingerTree (Node (Node a)) -> Digit (Node a) -> Node a -> Node a -> Node a -> Digit (Node a) -> FingerTree (Node (Node a)) -> FingerTree (Node (Node a)) addDigits3 m1 (One a) b c d (One e) m2 = appendTree2 m1 (node3 a b c) (node2 d e) m2 addDigits3 m1 (One a) b c d (Two e f) m2 = appendTree2 m1 (node3 a b c) (node3 d e f) m2 addDigits3 m1 (One a) b c d (Three e f g) m2 = appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2 addDigits3 m1 (One a) b c d (Four e f g h) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2 addDigits3 m1 (Two a b) c d e (One f) m2 = appendTree2 m1 (node3 a b c) (node3 d e f) m2 addDigits3 m1 (Two a b) c d e (Two f g) m2 = appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2 addDigits3 m1 (Two a b) c d e (Three f g h) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2 addDigits3 m1 (Two a b) c d e (Four f g h i) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2 addDigits3 m1 (Three a b c) d e f (One g) m2 = appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2 addDigits3 m1 (Three a b c) d e f (Two g h) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2 addDigits3 m1 (Three a b c) d e f (Three g h i) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2 addDigits3 m1 (Three a b c) d e f (Four g h i j) m2 = appendTree4 m1 (node3 a b c) (node3 d e f) (node2 g h) (node2 i j) m2 addDigits3 m1 (Four a b c d) e f g (One h) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2 addDigits3 m1 (Four a b c d) e f g (Two h i) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2 addDigits3 m1 (Four a b c d) e f g (Three h i j) m2 = appendTree4 m1 (node3 a b c) (node3 d e f) (node2 g h) (node2 i j) m2 addDigits3 m1 (Four a b c d) e f g (Four h i j k) m2 = appendTree4 m1 (node3 a b c) (node3 d e f) (node3 g h i) (node2 j k) m2 appendTree4 :: FingerTree (Node a) -> Node a -> Node a -> Node a -> Node a -> FingerTree (Node a) -> FingerTree (Node a) appendTree4 Empty a b c d xs = a `consTree` b `consTree` c `consTree` d `consTree` xs appendTree4 xs a b c d Empty = xs `snocTree` a `snocTree` b `snocTree` c `snocTree` d appendTree4 (Single x) a b c d xs = x `consTree` a `consTree` b `consTree` c `consTree` d `consTree` xs appendTree4 xs a b c d (Single x) = xs `snocTree` a `snocTree` b `snocTree` c `snocTree` d `snocTree` x appendTree4 (Deep s1 pr1 m1 sf1) a b c d (Deep s2 pr2 m2 sf2) = Deep (s1 + size a + size b + size c + size d + s2) pr1 (addDigits4 m1 sf1 a b c d pr2 m2) sf2 addDigits4 :: FingerTree (Node (Node a)) -> Digit (Node a) -> Node a -> Node a -> Node a -> Node a -> Digit (Node a) -> FingerTree (Node (Node a)) -> FingerTree (Node (Node a)) addDigits4 m1 (One a) b c d e (One f) m2 = appendTree2 m1 (node3 a b c) (node3 d e f) m2 addDigits4 m1 (One a) b c d e (Two f g) m2 = appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2 addDigits4 m1 (One a) b c d e (Three f g h) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2 addDigits4 m1 (One a) b c d e (Four f g h i) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2 addDigits4 m1 (Two a b) c d e f (One g) m2 = appendTree3 m1 (node3 a b c) (node2 d e) (node2 f g) m2 addDigits4 m1 (Two a b) c d e f (Two g h) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2 addDigits4 m1 (Two a b) c d e f (Three g h i) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2 addDigits4 m1 (Two a b) c d e f (Four g h i j) m2 = appendTree4 m1 (node3 a b c) (node3 d e f) (node2 g h) (node2 i j) m2 addDigits4 m1 (Three a b c) d e f g (One h) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node2 g h) m2 addDigits4 m1 (Three a b c) d e f g (Two h i) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2 addDigits4 m1 (Three a b c) d e f g (Three h i j) m2 = appendTree4 m1 (node3 a b c) (node3 d e f) (node2 g h) (node2 i j) m2 addDigits4 m1 (Three a b c) d e f g (Four h i j k) m2 = appendTree4 m1 (node3 a b c) (node3 d e f) (node3 g h i) (node2 j k) m2 addDigits4 m1 (Four a b c d) e f g h (One i) m2 = appendTree3 m1 (node3 a b c) (node3 d e f) (node3 g h i) m2 addDigits4 m1 (Four a b c d) e f g h (Two i j) m2 = appendTree4 m1 (node3 a b c) (node3 d e f) (node2 g h) (node2 i j) m2 addDigits4 m1 (Four a b c d) e f g h (Three i j k) m2 = appendTree4 m1 (node3 a b c) (node3 d e f) (node3 g h i) (node2 j k) m2 addDigits4 m1 (Four a b c d) e f g h (Four i j k l) m2 = appendTree4 m1 (node3 a b c) (node3 d e f) (node3 g h i) (node3 j k l) m2 -- | Builds a sequence from a seed value. Takes time linear in the -- number of generated elements. /WARNING:/ If the number of generated -- elements is infinite, this method will not terminate. unfoldr :: (b -> Maybe (a, b)) -> b -> Seq a unfoldr f = unfoldr' empty -- uses tail recursion rather than, for instance, the List implementation. where unfoldr' as b = maybe as (\ (a, b') -> unfoldr' (as |> a) b') (f b) -- | @'unfoldl' f x@ is equivalent to @'reverse' ('unfoldr' ('fmap' swap . f) x)@. unfoldl :: (b -> Maybe (b, a)) -> b -> Seq a unfoldl f = unfoldl' empty where unfoldl' as b = maybe as (\ (b', a) -> unfoldl' (a <| as) b') (f b) -- | /O(n)/. Constructs a sequence by repeated application of a function -- to a seed value. -- -- > iterateN n f x = fromList (Prelude.take n (Prelude.iterate f x)) iterateN :: Int -> (a -> a) -> a -> Seq a iterateN n f x | n >= 0 = replicateA n (State (\ y -> (f y, y))) `execState` x | otherwise = error "iterateN takes a nonnegative integer argument" ------------------------------------------------------------------------ -- Deconstruction ------------------------------------------------------------------------ -- | /O(1)/. Is this the empty sequence? null :: Seq a -> Bool null (Seq Empty) = True null _ = False -- | /O(1)/. The number of elements in the sequence. length :: Seq a -> Int length (Seq xs) = size xs -- Views data Maybe2 a b = Nothing2 | Just2 a b -- | View of the left end of a sequence. data ViewL a = EmptyL -- ^ empty sequence | a :< Seq a -- ^ leftmost element and the rest of the sequence #if __GLASGOW_HASKELL__ deriving (Eq, Ord, Show, Read, Data) #else deriving (Eq, Ord, Show, Read) #endif INSTANCE_TYPEABLE1(ViewL,viewLTc,"ViewL") instance Functor ViewL where {-# INLINE fmap #-} fmap _ EmptyL = EmptyL fmap f (x :< xs) = f x :< fmap f xs instance Foldable ViewL where foldr _ z EmptyL = z foldr f z (x :< xs) = f x (foldr f z xs) foldl _ z EmptyL = z foldl f z (x :< xs) = foldl f (f z x) xs foldl1 _ EmptyL = error "foldl1: empty view" foldl1 f (x :< xs) = foldl f x xs instance Traversable ViewL where traverse _ EmptyL = pure EmptyL traverse f (x :< xs) = (:<) <$> f x <*> traverse f xs -- | /O(1)/. Analyse the left end of a sequence. viewl :: Seq a -> ViewL a viewl (Seq xs) = case viewLTree xs of Nothing2 -> EmptyL Just2 (Elem x) xs' -> x :< Seq xs' {-# SPECIALIZE viewLTree :: FingerTree (Elem a) -> Maybe2 (Elem a) (FingerTree (Elem a)) #-} {-# SPECIALIZE viewLTree :: FingerTree (Node a) -> Maybe2 (Node a) (FingerTree (Node a)) #-} viewLTree :: Sized a => FingerTree a -> Maybe2 a (FingerTree a) viewLTree Empty = Nothing2 viewLTree (Single a) = Just2 a Empty viewLTree (Deep s (One a) m sf) = Just2 a (pullL (s - size a) m sf) viewLTree (Deep s (Two a b) m sf) = Just2 a (Deep (s - size a) (One b) m sf) viewLTree (Deep s (Three a b c) m sf) = Just2 a (Deep (s - size a) (Two b c) m sf) viewLTree (Deep s (Four a b c d) m sf) = Just2 a (Deep (s - size a) (Three b c d) m sf) -- | View of the right end of a sequence. data ViewR a = EmptyR -- ^ empty sequence | Seq a :> a -- ^ the sequence minus the rightmost element, -- and the rightmost element #if __GLASGOW_HASKELL__ deriving (Eq, Ord, Show, Read, Data) #else deriving (Eq, Ord, Show, Read) #endif INSTANCE_TYPEABLE1(ViewR,viewRTc,"ViewR") instance Functor ViewR where {-# INLINE fmap #-} fmap _ EmptyR = EmptyR fmap f (xs :> x) = fmap f xs :> f x instance Foldable ViewR where foldr _ z EmptyR = z foldr f z (xs :> x) = foldr f (f x z) xs foldl _ z EmptyR = z foldl f z (xs :> x) = foldl f z xs `f` x foldr1 _ EmptyR = error "foldr1: empty view" foldr1 f (xs :> x) = foldr f x xs instance Traversable ViewR where traverse _ EmptyR = pure EmptyR traverse f (xs :> x) = (:>) <$> traverse f xs <*> f x -- | /O(1)/. Analyse the right end of a sequence. viewr :: Seq a -> ViewR a viewr (Seq xs) = case viewRTree xs of Nothing2 -> EmptyR Just2 xs' (Elem x) -> Seq xs' :> x {-# SPECIALIZE viewRTree :: FingerTree (Elem a) -> Maybe2 (FingerTree (Elem a)) (Elem a) #-} {-# SPECIALIZE viewRTree :: FingerTree (Node a) -> Maybe2 (FingerTree (Node a)) (Node a) #-} viewRTree :: Sized a => FingerTree a -> Maybe2 (FingerTree a) a viewRTree Empty = Nothing2 viewRTree (Single z) = Just2 Empty z viewRTree (Deep s pr m (One z)) = Just2 (pullR (s - size z) pr m) z viewRTree (Deep s pr m (Two y z)) = Just2 (Deep (s - size z) pr m (One y)) z viewRTree (Deep s pr m (Three x y z)) = Just2 (Deep (s - size z) pr m (Two x y)) z viewRTree (Deep s pr m (Four w x y z)) = Just2 (Deep (s - size z) pr m (Three w x y)) z ------------------------------------------------------------------------ -- Scans -- -- These are not particularly complex applications of the Traversable -- functor, though making the correspondence with Data.List exact -- requires the use of (<|) and (|>). -- -- Note that save for the single (<|) or (|>), we maintain the original -- structure of the Seq, not having to do any restructuring of our own. -- -- wasserman.louis@gmail.com, 5/23/09 ------------------------------------------------------------------------ -- | 'scanl' is similar to 'foldl', but returns a sequence of reduced -- values from the left: -- -- > scanl f z (fromList [x1, x2, ...]) = fromList [z, z `f` x1, (z `f` x1) `f` x2, ...] scanl :: (a -> b -> a) -> a -> Seq b -> Seq a scanl f z0 xs = z0 <| snd (mapAccumL (\ x z -> let x' = f x z in (x', x')) z0 xs) -- | 'scanl1' is a variant of 'scanl' that has no starting value argument: -- -- > scanl1 f (fromList [x1, x2, ...]) = fromList [x1, x1 `f` x2, ...] scanl1 :: (a -> a -> a) -> Seq a -> Seq a scanl1 f xs = case viewl xs of EmptyL -> error "scanl1 takes a nonempty sequence as an argument" x :< xs' -> scanl f x xs' -- | 'scanr' is the right-to-left dual of 'scanl'. scanr :: (a -> b -> b) -> b -> Seq a -> Seq b scanr f z0 xs = snd (mapAccumR (\ z x -> let z' = f x z in (z', z')) z0 xs) |> z0 -- | 'scanr1' is a variant of 'scanr' that has no starting value argument. scanr1 :: (a -> a -> a) -> Seq a -> Seq a scanr1 f xs = case viewr xs of EmptyR -> error "scanr1 takes a nonempty sequence as an argument" xs' :> x -> scanr f x xs' -- Indexing -- | /O(log(min(i,n-i)))/. The element at the specified position, -- counting from 0. The argument should thus be a non-negative -- integer less than the size of the sequence. -- If the position is out of range, 'index' fails with an error. index :: Seq a -> Int -> a index (Seq xs) i | 0 <= i && i < size xs = case lookupTree i xs of Place _ (Elem x) -> x | otherwise = error "index out of bounds" data Place a = Place {-# UNPACK #-} !Int a #if TESTING deriving Show #endif {-# SPECIALIZE lookupTree :: Int -> FingerTree (Elem a) -> Place (Elem a) #-} {-# SPECIALIZE lookupTree :: Int -> FingerTree (Node a) -> Place (Node a) #-} lookupTree :: Sized a => Int -> FingerTree a -> Place a lookupTree _ Empty = error "lookupTree of empty tree" lookupTree i (Single x) = Place i x lookupTree i (Deep _ pr m sf) | i < spr = lookupDigit i pr | i < spm = case lookupTree (i - spr) m of Place i' xs -> lookupNode i' xs | otherwise = lookupDigit (i - spm) sf where spr = size pr spm = spr + size m {-# SPECIALIZE lookupNode :: Int -> Node (Elem a) -> Place (Elem a) #-} {-# SPECIALIZE lookupNode :: Int -> Node (Node a) -> Place (Node a) #-} lookupNode :: Sized a => Int -> Node a -> Place a lookupNode i (Node2 _ a b) | i < sa = Place i a | otherwise = Place (i - sa) b where sa = size a lookupNode i (Node3 _ a b c) | i < sa = Place i a | i < sab = Place (i - sa) b | otherwise = Place (i - sab) c where sa = size a sab = sa + size b {-# SPECIALIZE lookupDigit :: Int -> Digit (Elem a) -> Place (Elem a) #-} {-# SPECIALIZE lookupDigit :: Int -> Digit (Node a) -> Place (Node a) #-} lookupDigit :: Sized a => Int -> Digit a -> Place a lookupDigit i (One a) = Place i a lookupDigit i (Two a b) | i < sa = Place i a | otherwise = Place (i - sa) b where sa = size a lookupDigit i (Three a b c) | i < sa = Place i a | i < sab = Place (i - sa) b | otherwise = Place (i - sab) c where sa = size a sab = sa + size b lookupDigit i (Four a b c d) | i < sa = Place i a | i < sab = Place (i - sa) b | i < sabc = Place (i - sab) c | otherwise = Place (i - sabc) d where sa = size a sab = sa + size b sabc = sab + size c -- | /O(log(min(i,n-i)))/. Replace the element at the specified position. -- If the position is out of range, the original sequence is returned. update :: Int -> a -> Seq a -> Seq a update i x = adjust (const x) i -- | /O(log(min(i,n-i)))/. Update the element at the specified position. -- If the position is out of range, the original sequence is returned. adjust :: (a -> a) -> Int -> Seq a -> Seq a adjust f i (Seq xs) | 0 <= i && i < size xs = Seq (adjustTree (const (fmap f)) i xs) | otherwise = Seq xs {-# SPECIALIZE adjustTree :: (Int -> Elem a -> Elem a) -> Int -> FingerTree (Elem a) -> FingerTree (Elem a) #-} {-# SPECIALIZE adjustTree :: (Int -> Node a -> Node a) -> Int -> FingerTree (Node a) -> FingerTree (Node a) #-} adjustTree :: Sized a => (Int -> a -> a) -> Int -> FingerTree a -> FingerTree a adjustTree _ _ Empty = error "adjustTree of empty tree" adjustTree f i (Single x) = Single (f i x) adjustTree f i (Deep s pr m sf) | i < spr = Deep s (adjustDigit f i pr) m sf | i < spm = Deep s pr (adjustTree (adjustNode f) (i - spr) m) sf | otherwise = Deep s pr m (adjustDigit f (i - spm) sf) where spr = size pr spm = spr + size m {-# SPECIALIZE adjustNode :: (Int -> Elem a -> Elem a) -> Int -> Node (Elem a) -> Node (Elem a) #-} {-# SPECIALIZE adjustNode :: (Int -> Node a -> Node a) -> Int -> Node (Node a) -> Node (Node a) #-} adjustNode :: Sized a => (Int -> a -> a) -> Int -> Node a -> Node a adjustNode f i (Node2 s a b) | i < sa = Node2 s (f i a) b | otherwise = Node2 s a (f (i - sa) b) where sa = size a adjustNode f i (Node3 s a b c) | i < sa = Node3 s (f i a) b c | i < sab = Node3 s a (f (i - sa) b) c | otherwise = Node3 s a b (f (i - sab) c) where sa = size a sab = sa + size b {-# SPECIALIZE adjustDigit :: (Int -> Elem a -> Elem a) -> Int -> Digit (Elem a) -> Digit (Elem a) #-} {-# SPECIALIZE adjustDigit :: (Int -> Node a -> Node a) -> Int -> Digit (Node a) -> Digit (Node a) #-} adjustDigit :: Sized a => (Int -> a -> a) -> Int -> Digit a -> Digit a adjustDigit f i (One a) = One (f i a) adjustDigit f i (Two a b) | i < sa = Two (f i a) b | otherwise = Two a (f (i - sa) b) where sa = size a adjustDigit f i (Three a b c) | i < sa = Three (f i a) b c | i < sab = Three a (f (i - sa) b) c | otherwise = Three a b (f (i - sab) c) where sa = size a sab = sa + size b adjustDigit f i (Four a b c d) | i < sa = Four (f i a) b c d | i < sab = Four a (f (i - sa) b) c d | i < sabc = Four a b (f (i - sab) c) d | otherwise = Four a b c (f (i- sabc) d) where sa = size a sab = sa + size b sabc = sab + size c -- | A generalization of 'fmap', 'mapWithIndex' takes a mapping function -- that also depends on the element's index, and applies it to every -- element in the sequence. mapWithIndex :: (Int -> a -> b) -> Seq a -> Seq b mapWithIndex f xs = snd (mapAccumL' (\ i x -> (i + 1, f i x)) 0 xs) -- Splitting -- | /O(log(min(i,n-i)))/. The first @i@ elements of a sequence. -- If @i@ is negative, @'take' i s@ yields the empty sequence. -- If the sequence contains fewer than @i@ elements, the whole sequence -- is returned. take :: Int -> Seq a -> Seq a take i = fst . splitAt i -- | /O(log(min(i,n-i)))/. Elements of a sequence after the first @i@. -- If @i@ is negative, @'drop' i s@ yields the whole sequence. -- If the sequence contains fewer than @i@ elements, the empty sequence -- is returned. drop :: Int -> Seq a -> Seq a drop i = snd . splitAt i -- | /O(log(min(i,n-i)))/. Split a sequence at a given position. -- @'splitAt' i s = ('take' i s, 'drop' i s)@. splitAt :: Int -> Seq a -> (Seq a, Seq a) splitAt i (Seq xs) = (Seq l, Seq r) where (l, r) = split i xs split :: Int -> FingerTree (Elem a) -> (FingerTree (Elem a), FingerTree (Elem a)) split i Empty = i `seq` (Empty, Empty) split i xs | size xs > i = (l, consTree x r) | otherwise = (xs, Empty) where Split l x r = splitTree i xs data Split t a = Split t a t #if TESTING deriving Show #endif {-# SPECIALIZE splitTree :: Int -> FingerTree (Elem a) -> Split (FingerTree (Elem a)) (Elem a) #-} {-# SPECIALIZE splitTree :: Int -> FingerTree (Node a) -> Split (FingerTree (Node a)) (Node a) #-} splitTree :: Sized a => Int -> FingerTree a -> Split (FingerTree a) a splitTree _ Empty = error "splitTree of empty tree" splitTree i (Single x) = i `seq` Split Empty x Empty splitTree i (Deep _ pr m sf) | i < spr = case splitDigit i pr of Split l x r -> Split (maybe Empty digitToTree l) x (deepL r m sf) | i < spm = case splitTree im m of Split ml xs mr -> case splitNode (im - size ml) xs of Split l x r -> Split (deepR pr ml l) x (deepL r mr sf) | otherwise = case splitDigit (i - spm) sf of Split l x r -> Split (deepR pr m l) x (maybe Empty digitToTree r) where spr = size pr spm = spr + size m im = i - spr {-# SPECIALIZE splitNode :: Int -> Node (Elem a) -> Split (Maybe (Digit (Elem a))) (Elem a) #-} {-# SPECIALIZE splitNode :: Int -> Node (Node a) -> Split (Maybe (Digit (Node a))) (Node a) #-} splitNode :: Sized a => Int -> Node a -> Split (Maybe (Digit a)) a splitNode i (Node2 _ a b) | i < sa = Split Nothing a (Just (One b)) | otherwise = Split (Just (One a)) b Nothing where sa = size a splitNode i (Node3 _ a b c) | i < sa = Split Nothing a (Just (Two b c)) | i < sab = Split (Just (One a)) b (Just (One c)) | otherwise = Split (Just (Two a b)) c Nothing where sa = size a sab = sa + size b {-# SPECIALIZE splitDigit :: Int -> Digit (Elem a) -> Split (Maybe (Digit (Elem a))) (Elem a) #-} {-# SPECIALIZE splitDigit :: Int -> Digit (Node a) -> Split (Maybe (Digit (Node a))) (Node a) #-} splitDigit :: Sized a => Int -> Digit a -> Split (Maybe (Digit a)) a splitDigit i (One a) = i `seq` Split Nothing a Nothing splitDigit i (Two a b) | i < sa = Split Nothing a (Just (One b)) | otherwise = Split (Just (One a)) b Nothing where sa = size a splitDigit i (Three a b c) | i < sa = Split Nothing a (Just (Two b c)) | i < sab = Split (Just (One a)) b (Just (One c)) | otherwise = Split (Just (Two a b)) c Nothing where sa = size a sab = sa + size b splitDigit i (Four a b c d) | i < sa = Split Nothing a (Just (Three b c d)) | i < sab = Split (Just (One a)) b (Just (Two c d)) | i < sabc = Split (Just (Two a b)) c (Just (One d)) | otherwise = Split (Just (Three a b c)) d Nothing where sa = size a sab = sa + size b sabc = sab + size c -- | /O(n)/. Returns a sequence of all suffixes of this sequence, -- longest first. For example, -- -- > tails (fromList "abc") = fromList [fromList "abc", fromList "bc", fromList "c", fromList ""] -- -- Evaluating the /i/th suffix takes /O(log(min(i, n-i)))/, but evaluating -- every suffix in the sequence takes /O(n)/ due to sharing. tails :: Seq a -> Seq (Seq a) tails (Seq xs) = Seq (tailsTree (Elem . Seq) xs) |> empty -- | /O(n)/. Returns a sequence of all prefixes of this sequence, -- shortest first. For example, -- -- > inits (fromList "abc") = fromList [fromList "", fromList "a", fromList "ab", fromList "abc"] -- -- Evaluating the /i/th prefix takes /O(log(min(i, n-i)))/, but evaluating -- every prefix in the sequence takes /O(n)/ due to sharing. inits :: Seq a -> Seq (Seq a) inits (Seq xs) = empty <| Seq (initsTree (Elem . Seq) xs) -- This implementation of tails (and, analogously, inits) has the -- following algorithmic advantages: -- Evaluating each tail in the sequence takes linear total time, -- which is better than we could say for -- @fromList [drop n xs | n <- [0..length xs]]@. -- Evaluating any individual tail takes logarithmic time, which is -- better than we can say for either -- @scanr (<|) empty xs@ or @iterateN (length xs + 1) (\ xs -> let _ :< xs' = viewl xs in xs') xs@. -- -- Moreover, if we actually look at every tail in the sequence, the -- following benchmarks demonstrate that this implementation is modestly -- faster than any of the above: -- -- Times (ms) -- min mean +/-sd median max -- Seq.tails: 21.986 24.961 10.169 22.417 86.485 -- scanr: 85.392 87.942 2.488 87.425 100.217 -- iterateN: 29.952 31.245 1.574 30.412 37.268 -- -- The algorithm for tails (and, analogously, inits) is as follows: -- -- A Node in the FingerTree of tails is constructed by evaluating the -- corresponding tail of the FingerTree of Nodes, considering the first -- Node in this tail, and constructing a Node in which each tail of this -- Node is made to be the prefix of the remaining tree. This ends up -- working quite elegantly, as the remainder of the tail of the FingerTree -- of Nodes becomes the middle of a new tail, the suffix of the Node is -- the prefix, and the suffix of the original tree is retained. -- -- In particular, evaluating the /i/th tail involves making as -- many partial evaluations as the Node depth of the /i/th element. -- In addition, when we evaluate the /i/th tail, and we also evaluate -- the /j/th tail, and /m/ Nodes are on the path to both /i/ and /j/, -- each of those /m/ evaluations are shared between the computation of -- the /i/th and /j/th tails. -- -- wasserman.louis@gmail.com, 7/16/09 tailsDigit :: Digit a -> Digit (Digit a) tailsDigit (One a) = One (One a) tailsDigit (Two a b) = Two (Two a b) (One b) tailsDigit (Three a b c) = Three (Three a b c) (Two b c) (One c) tailsDigit (Four a b c d) = Four (Four a b c d) (Three b c d) (Two c d) (One d) initsDigit :: Digit a -> Digit (Digit a) initsDigit (One a) = One (One a) initsDigit (Two a b) = Two (One a) (Two a b) initsDigit (Three a b c) = Three (One a) (Two a b) (Three a b c) initsDigit (Four a b c d) = Four (One a) (Two a b) (Three a b c) (Four a b c d) tailsNode :: Node a -> Node (Digit a) tailsNode (Node2 s a b) = Node2 s (Two a b) (One b) tailsNode (Node3 s a b c) = Node3 s (Three a b c) (Two b c) (One c) initsNode :: Node a -> Node (Digit a) initsNode (Node2 s a b) = Node2 s (One a) (Two a b) initsNode (Node3 s a b c) = Node3 s (One a) (Two a b) (Three a b c) {-# SPECIALIZE tailsTree :: (FingerTree (Elem a) -> Elem b) -> FingerTree (Elem a) -> FingerTree (Elem b) #-} {-# SPECIALIZE tailsTree :: (FingerTree (Node a) -> Node b) -> FingerTree (Node a) -> FingerTree (Node b) #-} -- | Given a function to apply to tails of a tree, applies that function -- to every tail of the specified tree. tailsTree :: (Sized a, Sized b) => (FingerTree a -> b) -> FingerTree a -> FingerTree b tailsTree _ Empty = Empty tailsTree f (Single x) = Single (f (Single x)) tailsTree f (Deep n pr m sf) = Deep n (fmap (\ pr' -> f (deep pr' m sf)) (tailsDigit pr)) (tailsTree f' m) (fmap (f . digitToTree) (tailsDigit sf)) where f' ms = let Just2 node m' = viewLTree ms in fmap (\ pr' -> f (deep pr' m' sf)) (tailsNode node) {-# SPECIALIZE initsTree :: (FingerTree (Elem a) -> Elem b) -> FingerTree (Elem a) -> FingerTree (Elem b) #-} {-# SPECIALIZE initsTree :: (FingerTree (Node a) -> Node b) -> FingerTree (Node a) -> FingerTree (Node b) #-} -- | Given a function to apply to inits of a tree, applies that function -- to every init of the specified tree. initsTree :: (Sized a, Sized b) => (FingerTree a -> b) -> FingerTree a -> FingerTree b initsTree _ Empty = Empty initsTree f (Single x) = Single (f (Single x)) initsTree f (Deep n pr m sf) = Deep n (fmap (f . digitToTree) (initsDigit pr)) (initsTree f' m) (fmap (f . deep pr m) (initsDigit sf)) where f' ms = let Just2 m' node = viewRTree ms in fmap (\ sf' -> f (deep pr m' sf')) (initsNode node) {-# INLINE foldlWithIndex #-} -- | 'foldlWithIndex' is a version of 'foldl' that also provides access -- to the index of each element. foldlWithIndex :: (b -> Int -> a -> b) -> b -> Seq a -> b foldlWithIndex f z xs = foldl (\ g x i -> i `seq` f (g (i - 1)) i x) (const z) xs (length xs - 1) {-# INLINE foldrWithIndex #-} -- | 'foldrWithIndex' is a version of 'foldr' that also provides access -- to the index of each element. foldrWithIndex :: (Int -> a -> b -> b) -> b -> Seq a -> b foldrWithIndex f z xs = foldr (\ x g i -> i `seq` f i x (g (i+1))) (const z) xs 0 {-# INLINE listToMaybe' #-} -- 'listToMaybe\'' is a good consumer version of 'listToMaybe'. listToMaybe' :: [a] -> Maybe a listToMaybe' = foldr (\ x _ -> Just x) Nothing -- | /O(i)/ where /i/ is the prefix length. 'takeWhileL', applied -- to a predicate @p@ and a sequence @xs@, returns the longest prefix -- (possibly empty) of @xs@ of elements that satisfy @p@. takeWhileL :: (a -> Bool) -> Seq a -> Seq a takeWhileL p = fst . spanl p -- | /O(i)/ where /i/ is the suffix length. 'takeWhileR', applied -- to a predicate @p@ and a sequence @xs@, returns the longest suffix -- (possibly empty) of @xs@ of elements that satisfy @p@. -- -- @'takeWhileR' p xs@ is equivalent to @'reverse' ('takeWhileL' p ('reverse' xs))@. takeWhileR :: (a -> Bool) -> Seq a -> Seq a takeWhileR p = fst . spanr p -- | /O(i)/ where /i/ is the prefix length. @'dropWhileL' p xs@ returns -- the suffix remaining after @'takeWhileL' p xs@. dropWhileL :: (a -> Bool) -> Seq a -> Seq a dropWhileL p = snd . spanl p -- | /O(i)/ where /i/ is the suffix length. @'dropWhileR' p xs@ returns -- the prefix remaining after @'takeWhileR' p xs@. -- -- @'dropWhileR' p xs@ is equivalent to @'reverse' ('dropWhileL' p ('reverse' xs))@. dropWhileR :: (a -> Bool) -> Seq a -> Seq a dropWhileR p = snd . spanr p -- | /O(i)/ where /i/ is the prefix length. 'spanl', applied to -- a predicate @p@ and a sequence @xs@, returns a pair whose first -- element is the longest prefix (possibly empty) of @xs@ of elements that -- satisfy @p@ and the second element is the remainder of the sequence. spanl :: (a -> Bool) -> Seq a -> (Seq a, Seq a) spanl p = breakl (not . p) -- | /O(i)/ where /i/ is the suffix length. 'spanr', applied to a -- predicate @p@ and a sequence @xs@, returns a pair whose /first/ element -- is the longest /suffix/ (possibly empty) of @xs@ of elements that -- satisfy @p@ and the second element is the remainder of the sequence. spanr :: (a -> Bool) -> Seq a -> (Seq a, Seq a) spanr p = breakr (not . p) {-# INLINE breakl #-} -- | /O(i)/ where /i/ is the breakpoint index. 'breakl', applied to a -- predicate @p@ and a sequence @xs@, returns a pair whose first element -- is the longest prefix (possibly empty) of @xs@ of elements that -- /do not satisfy/ @p@ and the second element is the remainder of -- the sequence. -- -- @'breakl' p@ is equivalent to @'spanl' (not . p)@. breakl :: (a -> Bool) -> Seq a -> (Seq a, Seq a) breakl p xs = foldr (\ i _ -> splitAt i xs) (xs, empty) (findIndicesL p xs) {-# INLINE breakr #-} -- | @'breakr' p@ is equivalent to @'spanr' (not . p)@. breakr :: (a -> Bool) -> Seq a -> (Seq a, Seq a) breakr p xs = foldr (\ i _ -> flipPair (splitAt (i + 1) xs)) (xs, empty) (findIndicesR p xs) where flipPair (x, y) = (y, x) -- | /O(n)/. The 'partition' function takes a predicate @p@ and a -- sequence @xs@ and returns sequences of those elements which do and -- do not satisfy the predicate. partition :: (a -> Bool) -> Seq a -> (Seq a, Seq a) partition p = foldl part (empty, empty) where part (xs, ys) x | p x = (xs |> x, ys) | otherwise = (xs, ys |> x) -- | /O(n)/. The 'filter' function takes a predicate @p@ and a sequence -- @xs@ and returns a sequence of those elements which satisfy the -- predicate. filter :: (a -> Bool) -> Seq a -> Seq a filter p = foldl (\ xs x -> if p x then xs |> x else xs) empty -- Indexing sequences -- | 'elemIndexL' finds the leftmost index of the specified element, -- if it is present, and otherwise 'Nothing'. elemIndexL :: Eq a => a -> Seq a -> Maybe Int elemIndexL x = findIndexL (x ==) -- | 'elemIndexR' finds the rightmost index of the specified element, -- if it is present, and otherwise 'Nothing'. elemIndexR :: Eq a => a -> Seq a -> Maybe Int elemIndexR x = findIndexR (x ==) -- | 'elemIndicesL' finds the indices of the specified element, from -- left to right (i.e. in ascending order). elemIndicesL :: Eq a => a -> Seq a -> [Int] elemIndicesL x = findIndicesL (x ==) -- | 'elemIndicesR' finds the indices of the specified element, from -- right to left (i.e. in descending order). elemIndicesR :: Eq a => a -> Seq a -> [Int] elemIndicesR x = findIndicesR (x ==) -- | @'findIndexL' p xs@ finds the index of the leftmost element that -- satisfies @p@, if any exist. findIndexL :: (a -> Bool) -> Seq a -> Maybe Int findIndexL p = listToMaybe' . findIndicesL p -- | @'findIndexR' p xs@ finds the index of the rightmost element that -- satisfies @p@, if any exist. findIndexR :: (a -> Bool) -> Seq a -> Maybe Int findIndexR p = listToMaybe' . findIndicesR p {-# INLINE findIndicesL #-} -- | @'findIndicesL' p@ finds all indices of elements that satisfy @p@, -- in ascending order. findIndicesL :: (a -> Bool) -> Seq a -> [Int] #if __GLASGOW_HASKELL__ findIndicesL p xs = build (\ c n -> let g i x z = if p x then c i z else z in foldrWithIndex g n xs) #else findIndicesL p xs = foldrWithIndex g [] xs where g i x is = if p x then i:is else is #endif {-# INLINE findIndicesR #-} -- | @'findIndicesR' p@ finds all indices of elements that satisfy @p@, -- in descending order. findIndicesR :: (a -> Bool) -> Seq a -> [Int] #if __GLASGOW_HASKELL__ findIndicesR p xs = build (\ c n -> let g z i x = if p x then c i z else z in foldlWithIndex g n xs) #else findIndicesR p xs = foldlWithIndex g [] xs where g is i x = if p x then i:is else is #endif ------------------------------------------------------------------------ -- Lists ------------------------------------------------------------------------ -- | /O(n)/. Create a sequence from a finite list of elements. -- There is a function 'toList' in the opposite direction for all -- instances of the 'Foldable' class, including 'Seq'. fromList :: [a] -> Seq a fromList = Data.List.foldl' (|>) empty ------------------------------------------------------------------------ -- Reverse ------------------------------------------------------------------------ -- | /O(n)/. The reverse of a sequence. reverse :: Seq a -> Seq a reverse (Seq xs) = Seq (reverseTree id xs) reverseTree :: (a -> a) -> FingerTree a -> FingerTree a reverseTree _ Empty = Empty reverseTree f (Single x) = Single (f x) reverseTree f (Deep s pr m sf) = Deep s (reverseDigit f sf) (reverseTree (reverseNode f) m) (reverseDigit f pr) {-# INLINE reverseDigit #-} reverseDigit :: (a -> a) -> Digit a -> Digit a reverseDigit f (One a) = One (f a) reverseDigit f (Two a b) = Two (f b) (f a) reverseDigit f (Three a b c) = Three (f c) (f b) (f a) reverseDigit f (Four a b c d) = Four (f d) (f c) (f b) (f a) reverseNode :: (a -> a) -> Node a -> Node a reverseNode f (Node2 s a b) = Node2 s (f b) (f a) reverseNode f (Node3 s a b c) = Node3 s (f c) (f b) (f a) ------------------------------------------------------------------------ -- Zipping ------------------------------------------------------------------------ -- | /O(min(n1,n2))/. 'zip' takes two sequences and returns a sequence -- of corresponding pairs. If one input is short, excess elements are -- discarded from the right end of the longer sequence. zip :: Seq a -> Seq b -> Seq (a, b) zip = zipWith (,) -- | /O(min(n1,n2))/. 'zipWith' generalizes 'zip' by zipping with the -- function given as the first argument, instead of a tupling function. -- For example, @zipWith (+)@ is applied to two sequences to take the -- sequence of corresponding sums. zipWith :: (a -> b -> c) -> Seq a -> Seq b -> Seq c zipWith f xs ys | length xs <= length ys = zipWith' f xs ys | otherwise = zipWith' (flip f) ys xs -- like 'zipWith', but assumes length xs <= length ys zipWith' :: (a -> b -> c) -> Seq a -> Seq b -> Seq c zipWith' f xs ys = snd (mapAccumL k ys xs) where k kys x = case viewl kys of (z :< zs) -> (zs, f x z) EmptyL -> error "zipWith': unexpected EmptyL" -- | /O(min(n1,n2,n3))/. 'zip3' takes three sequences and returns a -- sequence of triples, analogous to 'zip'. zip3 :: Seq a -> Seq b -> Seq c -> Seq (a,b,c) zip3 = zipWith3 (,,) -- | /O(min(n1,n2,n3))/. 'zipWith3' takes a function which combines -- three elements, as well as three sequences and returns a sequence of -- their point-wise combinations, analogous to 'zipWith'. zipWith3 :: (a -> b -> c -> d) -> Seq a -> Seq b -> Seq c -> Seq d zipWith3 f s1 s2 s3 = zipWith ($) (zipWith f s1 s2) s3 -- | /O(min(n1,n2,n3,n4))/. 'zip4' takes four sequences and returns a -- sequence of quadruples, analogous to 'zip'. zip4 :: Seq a -> Seq b -> Seq c -> Seq d -> Seq (a,b,c,d) zip4 = zipWith4 (,,,) -- | /O(min(n1,n2,n3,n4))/. 'zipWith4' takes a function which combines -- four elements, as well as four sequences and returns a sequence of -- their point-wise combinations, analogous to 'zipWith'. zipWith4 :: (a -> b -> c -> d -> e) -> Seq a -> Seq b -> Seq c -> Seq d -> Seq e zipWith4 f s1 s2 s3 s4 = zipWith ($) (zipWith ($) (zipWith f s1 s2) s3) s4 ------------------------------------------------------------------------ -- Sorting -- -- sort and sortBy are implemented by simple deforestations of -- \ xs -> fromList2 (length xs) . Data.List.sortBy cmp . toList -- which does not get deforested automatically, it would appear. -- -- Unstable sorting is performed by a heap sort implementation based on -- pairing heaps. Because the internal structure of sequences is quite -- varied, it is difficult to get blocks of elements of roughly the same -- length, which would improve merge sort performance. Pairing heaps, -- on the other hand, are relatively resistant to the effects of merging -- heaps of wildly different sizes, as guaranteed by its amortized -- constant-time merge operation. Moreover, extensive use of SpecConstr -- transformations can be done on pairing heaps, especially when we're -- only constructing them to immediately be unrolled. -- -- On purely random sequences of length 50000, with no RTS options, -- I get the following statistics, in which heapsort is about 42.5% -- faster: (all comparisons done with -O2) -- -- Times (ms) min mean +/-sd median max -- to/from list: 103.802 108.572 7.487 106.436 143.339 -- unstable heapsort: 60.686 62.968 4.275 61.187 79.151 -- -- Heapsort, it would seem, is less of a memory hog than Data.List.sortBy. -- The gap is narrowed when more memory is available, but heapsort still -- wins, 15% faster, with +RTS -H128m: -- -- Times (ms) min mean +/-sd median max -- to/from list: 42.692 45.074 2.596 44.600 56.601 -- unstable heapsort: 37.100 38.344 3.043 37.715 55.526 -- -- In addition, on strictly increasing sequences the gap is even wider -- than normal; heapsort is 68.5% faster with no RTS options: -- Times (ms) min mean +/-sd median max -- to/from list: 52.236 53.574 1.987 53.034 62.098 -- unstable heapsort: 16.433 16.919 0.931 16.681 21.622 -- -- This may be attributed to the elegant nature of the pairing heap. -- -- wasserman.louis@gmail.com, 7/20/09 ------------------------------------------------------------------------ -- | /O(n log n)/. 'sort' sorts the specified 'Seq' by the natural -- ordering of its elements. The sort is stable. -- If stability is not required, 'unstableSort' can be considerably -- faster, and in particular uses less memory. sort :: Ord a => Seq a -> Seq a sort = sortBy compare -- | /O(n log n)/. 'sortBy' sorts the specified 'Seq' according to the -- specified comparator. The sort is stable. -- If stability is not required, 'unstableSortBy' can be considerably -- faster, and in particular uses less memory. sortBy :: (a -> a -> Ordering) -> Seq a -> Seq a sortBy cmp xs = fromList2 (length xs) (Data.List.sortBy cmp (toList xs)) -- | /O(n log n)/. 'unstableSort' sorts the specified 'Seq' by -- the natural ordering of its elements, but the sort is not stable. -- This algorithm is frequently faster and uses less memory than 'sort', -- and performs extremely well -- frequently twice as fast as 'sort' -- -- when the sequence is already nearly sorted. unstableSort :: Ord a => Seq a -> Seq a unstableSort = unstableSortBy compare -- | /O(n log n)/. A generalization of 'unstableSort', 'unstableSortBy' -- takes an arbitrary comparator and sorts the specified sequence. -- The sort is not stable. This algorithm is frequently faster and -- uses less memory than 'sortBy', and performs extremely well -- -- frequently twice as fast as 'sortBy' -- when the sequence is already -- nearly sorted. unstableSortBy :: (a -> a -> Ordering) -> Seq a -> Seq a unstableSortBy cmp (Seq xs) = fromList2 (size xs) $ maybe [] (unrollPQ cmp) $ toPQ cmp (\ (Elem x) -> PQueue x Nil) xs -- | fromList2, given a list and its length, constructs a completely -- balanced Seq whose elements are that list using the applicativeTree -- generalization. fromList2 :: Int -> [a] -> Seq a fromList2 n = execState (replicateA n (State ht)) where ht (x:xs) = (xs, x) ht [] = error "fromList2: short list" -- | A 'PQueue' is a simple pairing heap. data PQueue e = PQueue e (PQL e) data PQL e = Nil | {-# UNPACK #-} !(PQueue e) :& PQL e infixr 8 :& #if TESTING instance Functor PQueue where fmap f (PQueue x ts) = PQueue (f x) (fmap f ts) instance Functor PQL where fmap f (q :& qs) = fmap f q :& fmap f qs fmap _ Nil = Nil instance Show e => Show (PQueue e) where show = unlines . draw . fmap show -- borrowed wholesale from Data.Tree, as Data.Tree actually depends -- on Data.Sequence draw :: PQueue String -> [String] draw (PQueue x ts0) = x : drawSubTrees ts0 where drawSubTrees Nil = [] drawSubTrees (t :& Nil) = "|" : shift "`- " " " (draw t) drawSubTrees (t :& ts) = "|" : shift "+- " "| " (draw t) ++ drawSubTrees ts shift first other = Data.List.zipWith (++) (first : repeat other) #endif -- | 'unrollPQ', given a comparator function, unrolls a 'PQueue' into -- a sorted list. unrollPQ :: (e -> e -> Ordering) -> PQueue e -> [e] unrollPQ cmp = unrollPQ' where {-# INLINE unrollPQ' #-} unrollPQ' (PQueue x ts) = x:mergePQs0 ts (<>) = mergePQ cmp mergePQs0 Nil = [] mergePQs0 (t :& Nil) = unrollPQ' t mergePQs0 (t1 :& t2 :& ts) = mergePQs (t1 <> t2) ts mergePQs t ts = t `seq` case ts of Nil -> unrollPQ' t t1 :& Nil -> unrollPQ' (t <> t1) t1 :& t2 :& ts' -> mergePQs (t <> (t1 <> t2)) ts' -- | 'toPQ', given an ordering function and a mechanism for queueifying -- elements, converts a 'FingerTree' to a 'PQueue'. toPQ :: (e -> e -> Ordering) -> (a -> PQueue e) -> FingerTree a -> Maybe (PQueue e) toPQ _ _ Empty = Nothing toPQ _ f (Single x) = Just (f x) toPQ cmp f (Deep _ pr m sf) = Just (maybe (pr' <> sf') ((pr' <> sf') <>) (toPQ cmp fNode m)) where fDigit digit = case fmap f digit of One a -> a Two a b -> a <> b Three a b c -> a <> b <> c Four a b c d -> (a <> b) <> (c <> d) (<>) = mergePQ cmp fNode = fDigit . nodeToDigit pr' = fDigit pr sf' = fDigit sf -- | 'mergePQ' merges two 'PQueue's. mergePQ :: (a -> a -> Ordering) -> PQueue a -> PQueue a -> PQueue a mergePQ cmp q1@(PQueue x1 ts1) q2@(PQueue x2 ts2) | cmp x1 x2 == GT = PQueue x2 (q1 :& ts2) | otherwise = PQueue x1 (q2 :& ts1)