| 1 | Wed Jul 29 13:03:09 EDT 2009 wasserman.louis@gmail.com |
|---|
| 2 | * Ticket #3271: New methods for Data.Sequence |
|---|
| 3 | |
|---|
| 4 | New patches: |
|---|
| 5 | |
|---|
| 6 | [Ticket #3271: New methods for Data.Sequence |
|---|
| 7 | wasserman.louis@gmail.com**20090729170309 |
|---|
| 8 | Ignore-this: d5a2ee4c7f2c4c30b994094a16310504 |
|---|
| 9 | ] { |
|---|
| 10 | hunk ./Data/Sequence.hs 6 |
|---|
| 11 | -- | |
|---|
| 12 | -- Module : Data.Sequence |
|---|
| 13 | -- Copyright : (c) Ross Paterson 2005 |
|---|
| 14 | +-- (c) Louis Wasserman 2009 |
|---|
| 15 | -- License : BSD-style |
|---|
| 16 | -- Maintainer : libraries@haskell.org |
|---|
| 17 | -- Stability : experimental |
|---|
| 18 | hunk ./Data/Sequence.hs 40 |
|---|
| 19 | -- * Construction |
|---|
| 20 | empty, -- :: Seq a |
|---|
| 21 | singleton, -- :: a -> Seq a |
|---|
| 22 | + replicate, -- :: Int -> a -> Seq a |
|---|
| 23 | (<|), -- :: a -> Seq a -> Seq a |
|---|
| 24 | (|>), -- :: Seq a -> a -> Seq a |
|---|
| 25 | (><), -- :: Seq a -> Seq a -> Seq a |
|---|
| 26 | hunk ./Data/Sequence.hs 45 |
|---|
| 27 | fromList, -- :: [a] -> Seq a |
|---|
| 28 | + -- ** Sequential construction |
|---|
| 29 | + iterateN, -- :: Int -> (a -> a) -> a -> Seq a |
|---|
| 30 | + unfoldr, -- :: (b -> Maybe (a, b)) -> b -> Seq a |
|---|
| 31 | + unfoldl, -- :: (b -> Maybe (b, a)) -> b -> Seq a |
|---|
| 32 | -- * Deconstruction |
|---|
| 33 | -- | Additional functions for deconstructing sequences are available |
|---|
| 34 | -- via the 'Foldable' instance of 'Seq'. |
|---|
| 35 | hunk ./Data/Sequence.hs 61 |
|---|
| 36 | viewl, -- :: Seq a -> ViewL a |
|---|
| 37 | ViewR(..), |
|---|
| 38 | viewr, -- :: Seq a -> ViewR a |
|---|
| 39 | + -- ** Scanning |
|---|
| 40 | + scanl, -- :: (a -> b -> a) -> a -> Seq b -> Seq a |
|---|
| 41 | + scanl1, -- :: (a -> a -> a) -> Seq a -> Seq a |
|---|
| 42 | + scanr, -- :: (a -> b -> b) -> b -> Seq a -> Seq b |
|---|
| 43 | + scanr1, -- :: (a -> a -> a) -> Seq a -> Seq a |
|---|
| 44 | + -- ** Sublists |
|---|
| 45 | + tails, -- :: Seq a -> Seq (Seq a) |
|---|
| 46 | + inits, -- :: Seq a -> Seq (Seq a) |
|---|
| 47 | + takeWhile, -- :: (a -> Bool) -> Seq a -> Seq a |
|---|
| 48 | + takeWhileEnd, -- :: (a -> Bool) -> Seq a -> Seq a |
|---|
| 49 | + dropWhile, -- :: (a -> Bool) -> Seq a -> Seq a |
|---|
| 50 | + dropWhileEnd, -- :: (a -> Bool) -> Seq a -> Seq a |
|---|
| 51 | + span, -- :: (a -> Bool) -> Seq a -> (Seq a, Seq a) |
|---|
| 52 | + spanEnd, -- :: (a -> Bool) -> Seq a -> (Seq a, Seq a) |
|---|
| 53 | + break, -- :: (a -> Bool) -> Seq a -> (Seq a, Seq a) |
|---|
| 54 | + breakEnd, -- :: (a -> Bool) -> Seq a -> (Seq a, Seq a) |
|---|
| 55 | + partition, -- :: (a -> Bool) -> Seq a -> (Seq a, Seq a) |
|---|
| 56 | + filter, -- :: (a -> Bool) -> Seq a -> Seq a |
|---|
| 57 | + -- ** Sorts |
|---|
| 58 | + sort, -- :: Ord a => Seq a -> Seq a |
|---|
| 59 | + sortBy, -- :: (a -> a -> Ordering) -> Seq a -> Seq a |
|---|
| 60 | + unstableSort, -- :: Ord a => Seq a -> Seq a |
|---|
| 61 | + unstableSortBy, -- :: (a -> a -> Ordering) -> Seq a -> Seq a |
|---|
| 62 | -- ** Indexing |
|---|
| 63 | index, -- :: Seq a -> Int -> a |
|---|
| 64 | adjust, -- :: (a -> a) -> Int -> Seq a -> Seq a |
|---|
| 65 | hunk ./Data/Sequence.hs 91 |
|---|
| 66 | take, -- :: Int -> Seq a -> Seq a |
|---|
| 67 | drop, -- :: Int -> Seq a -> Seq a |
|---|
| 68 | splitAt, -- :: Int -> Seq a -> (Seq a, Seq a) |
|---|
| 69 | + -- *** Indexing with predicates |
|---|
| 70 | + elemIndex, -- :: Eq a => a -> Seq a -> Maybe Int |
|---|
| 71 | + elemIndices, -- :: Eq a => a -> Seq a -> [Int] |
|---|
| 72 | + elemLastIndex, -- :: Eq a => a -> Seq a -> Maybe Ind |
|---|
| 73 | + elemIndicesDesc,-- :: Eq a => a -> Seq a -> [Int] |
|---|
| 74 | + findIndex, -- :: (a -> Bool) -> Seq a -> Maybe Int |
|---|
| 75 | + findIndices, -- :: (a -> Bool) -> Seq a -> [Int] |
|---|
| 76 | + findLastIndex, -- :: (a -> Bool) -> Seq a -> Maybe Int |
|---|
| 77 | + findIndicesDesc,-- :: (a -> Bool) -> Seq a -> [Int] |
|---|
| 78 | -- * Transformations |
|---|
| 79 | hunk ./Data/Sequence.hs 101 |
|---|
| 80 | + mapWithIndex, -- :: (Int -> a -> b) -> Seq a -> Seq b |
|---|
| 81 | reverse, -- :: Seq a -> Seq a |
|---|
| 82 | hunk ./Data/Sequence.hs 103 |
|---|
| 83 | + -- ** Zips |
|---|
| 84 | + zip, -- :: Seq a -> Seq b -> Seq (a, b) |
|---|
| 85 | + zipWith, -- :: (a -> b -> c) -> Seq a -> Seq b -> Seq c |
|---|
| 86 | + zip3, -- :: Seq a -> Seq b -> Seq c -> Seq (a, b, c) |
|---|
| 87 | + zipWith3, -- :: (a -> b -> c -> d) -> Seq a -> Seq b -> Seq c -> Seq d |
|---|
| 88 | + zip4, -- :: Seq a -> Seq b -> Seq c -> Seq d -> Seq (a, b, c, d) |
|---|
| 89 | + zipWith4, -- :: (a -> b -> c -> d -> e) -> Seq a -> Seq b -> Seq c -> Seq d -> Seq e |
|---|
| 90 | #if TESTING |
|---|
| 91 | valid, |
|---|
| 92 | #endif |
|---|
| 93 | hunk ./Data/Sequence.hs 116 |
|---|
| 94 | ) where |
|---|
| 95 | |
|---|
| 96 | import Prelude hiding ( |
|---|
| 97 | - null, length, take, drop, splitAt, foldl, foldl1, foldr, foldr1, |
|---|
| 98 | - reverse) |
|---|
| 99 | -import qualified Data.List (foldl') |
|---|
| 100 | -import Control.Applicative (Applicative(..), (<$>)) |
|---|
| 101 | -import Control.Monad (MonadPlus(..)) |
|---|
| 102 | + null, length, take, drop, splitAt, foldl, foldl1, foldr, foldr1, span, |
|---|
| 103 | + scanl, scanl1, scanr, scanr1, replicate, zip, zipWith, zip3, zipWith3, |
|---|
| 104 | + takeWhile, dropWhile, break, iterate, reverse, filter, mapM, all) |
|---|
| 105 | +import qualified Data.List (foldl', zipWith) |
|---|
| 106 | +import Control.Applicative (Applicative(..), (<$>), liftA, liftA2, liftA3) |
|---|
| 107 | +import Control.Monad (MonadPlus(..), ap, liftM, liftM2, liftM3, liftM4) |
|---|
| 108 | import Data.Monoid (Monoid(..)) |
|---|
| 109 | import Data.Foldable |
|---|
| 110 | import Data.Traversable |
|---|
| 111 | hunk ./Data/Sequence.hs 131 |
|---|
| 112 | import Data.Typeable (TyCon, Typeable1(..), mkTyCon, mkTyConApp ) |
|---|
| 113 | |
|---|
| 114 | #ifdef __GLASGOW_HASKELL__ |
|---|
| 115 | +import GHC.Exts (build) |
|---|
| 116 | import Text.Read (Lexeme(Ident), lexP, parens, prec, |
|---|
| 117 | readPrec, readListPrec, readListPrecDefault) |
|---|
| 118 | import Data.Data (Data(..), DataType, Constr, Fixity(..), |
|---|
| 119 | hunk ./Data/Sequence.hs 139 |
|---|
| 120 | #endif |
|---|
| 121 | |
|---|
| 122 | #if TESTING |
|---|
| 123 | -import Control.Monad (liftM, liftM3, liftM4) |
|---|
| 124 | -import Test.QuickCheck |
|---|
| 125 | +import Test.QuickCheck hiding ((><)) |
|---|
| 126 | #endif |
|---|
| 127 | |
|---|
| 128 | infixr 5 `consTree` |
|---|
| 129 | hunk ./Data/Sequence.hs 144 |
|---|
| 130 | infixl 5 `snocTree` |
|---|
| 131 | +infixr 5 `consDTree` |
|---|
| 132 | +infixl 6 `snocDTree` |
|---|
| 133 | |
|---|
| 134 | infixr 5 >< |
|---|
| 135 | infixr 5 <|, :< |
|---|
| 136 | hunk ./Data/Sequence.hs 298 |
|---|
| 137 | traverse f sf |
|---|
| 138 | |
|---|
| 139 | {-# INLINE deep #-} |
|---|
| 140 | -{-# SPECIALIZE deep :: Digit (Elem a) -> FingerTree (Node (Elem a)) -> Digit (Elem a) -> FingerTree (Elem a) #-} |
|---|
| 141 | -{-# SPECIALIZE deep :: Digit (Node a) -> FingerTree (Node (Node a)) -> Digit (Node a) -> FingerTree (Node a) #-} |
|---|
| 142 | +{-# SPECIALIZE INLINE deep :: Digit (Elem a) -> FingerTree (Node (Elem a)) -> Digit (Elem a) -> FingerTree (Elem a) #-} |
|---|
| 143 | +{-# SPECIALIZE INLINE deep :: Digit (Node a) -> FingerTree (Node (Node a)) -> Digit (Node a) -> FingerTree (Node a) #-} |
|---|
| 144 | deep :: Sized a => Digit a -> FingerTree (Node a) -> Digit a -> FingerTree a |
|---|
| 145 | deep pr m sf = Deep (size pr + size m + size sf) pr m sf |
|---|
| 146 | |
|---|
| 147 | hunk ./Data/Sequence.hs 303 |
|---|
| 148 | +{-# INLINE pullL #-} |
|---|
| 149 | +pullL :: Sized a => Int -> FingerTree (Node a) -> Digit a -> FingerTree a |
|---|
| 150 | +pullL s m sf = case viewLTree m of |
|---|
| 151 | + Nothing2 -> digitToTree' s sf |
|---|
| 152 | + Just2 pr m' -> Deep s (nodeToDigit pr) m' sf |
|---|
| 153 | + |
|---|
| 154 | +{-# INLINE pullR #-} |
|---|
| 155 | +pullR :: Sized a => Int -> Digit a -> FingerTree (Node a) -> FingerTree a |
|---|
| 156 | +pullR s pr m = case viewRTree m of |
|---|
| 157 | + Nothing2 -> digitToTree' s pr |
|---|
| 158 | + Just2 m' sf -> Deep s pr m' (nodeToDigit sf) |
|---|
| 159 | + |
|---|
| 160 | +{-# SPECIALIZE deepL :: Maybe (Digit (Elem a)) -> FingerTree (Node (Elem a)) -> Digit (Elem a) -> FingerTree (Elem a) #-} |
|---|
| 161 | +{-# SPECIALIZE deepL :: Maybe (Digit (Node a)) -> FingerTree (Node (Node a)) -> Digit (Node a) -> FingerTree (Node a) #-} |
|---|
| 162 | +deepL :: Sized a => Maybe (Digit a) -> FingerTree (Node a) -> Digit a -> FingerTree a |
|---|
| 163 | +deepL Nothing m sf = pullL (size m + size sf) m sf |
|---|
| 164 | +deepL (Just pr) m sf = deep pr m sf |
|---|
| 165 | + |
|---|
| 166 | +{-# SPECIALIZE deepR :: Digit (Elem a) -> FingerTree (Node (Elem a)) -> Maybe (Digit (Elem a)) -> FingerTree (Elem a) #-} |
|---|
| 167 | +{-# SPECIALIZE deepR :: Digit (Node a) -> FingerTree (Node (Node a)) -> Maybe (Digit (Node a)) -> FingerTree (Node a) #-} |
|---|
| 168 | +deepR :: Sized a => Digit a -> FingerTree (Node a) -> Maybe (Digit a) -> FingerTree a |
|---|
| 169 | +deepR pr m Nothing = pullR (size m + size pr) pr m |
|---|
| 170 | +deepR pr m (Just sf) = deep pr m sf |
|---|
| 171 | + |
|---|
| 172 | -- Digits |
|---|
| 173 | |
|---|
| 174 | data Digit a |
|---|
| 175 | hunk ./Data/Sequence.hs 363 |
|---|
| 176 | fmap = fmapDefault |
|---|
| 177 | |
|---|
| 178 | instance Traversable Digit where |
|---|
| 179 | + {-# INLINE traverse #-} |
|---|
| 180 | traverse f (One a) = One <$> f a |
|---|
| 181 | traverse f (Two a b) = Two <$> f a <*> f b |
|---|
| 182 | traverse f (Three a b c) = Three <$> f a <*> f b <*> f c |
|---|
| 183 | hunk ./Data/Sequence.hs 370 |
|---|
| 184 | traverse f (Four a b c d) = Four <$> f a <*> f b <*> f c <*> f d |
|---|
| 185 | |
|---|
| 186 | instance Sized a => Sized (Digit a) where |
|---|
| 187 | - {-# SPECIALIZE instance Sized (Digit (Elem a)) #-} |
|---|
| 188 | - {-# SPECIALIZE instance Sized (Digit (Node a)) #-} |
|---|
| 189 | - size xs = foldl (\ i x -> i + size x) 0 xs |
|---|
| 190 | + {-# INLINE size #-} |
|---|
| 191 | + size = foldl1 (+) . fmap size |
|---|
| 192 | |
|---|
| 193 | {-# SPECIALIZE digitToTree :: Digit (Elem a) -> FingerTree (Elem a) #-} |
|---|
| 194 | {-# SPECIALIZE digitToTree :: Digit (Node a) -> FingerTree (Node a) #-} |
|---|
| 195 | hunk ./Data/Sequence.hs 381 |
|---|
| 196 | digitToTree (Three a b c) = deep (Two a b) Empty (One c) |
|---|
| 197 | digitToTree (Four a b c d) = deep (Two a b) Empty (Two c d) |
|---|
| 198 | |
|---|
| 199 | +-- | Given the size of a digit and the digit itself, efficiently converts it to a FingerTree. |
|---|
| 200 | +digitToTree' :: Int -> Digit a -> FingerTree a |
|---|
| 201 | +digitToTree' n (Four a b c d) = Deep n (Two a b) Empty (Two c d) |
|---|
| 202 | +digitToTree' n (Three a b c) = Deep n (Two a b) Empty (One c) |
|---|
| 203 | +digitToTree' n (Two a b) = Deep n (One a) Empty (One b) |
|---|
| 204 | +digitToTree' n (One a) = n `seq` Single a |
|---|
| 205 | + |
|---|
| 206 | + |
|---|
| 207 | + |
|---|
| 208 | -- Nodes |
|---|
| 209 | |
|---|
| 210 | data Node a |
|---|
| 211 | hunk ./Data/Sequence.hs 407 |
|---|
| 212 | foldl f z (Node3 _ a b c) = ((z `f` a) `f` b) `f` c |
|---|
| 213 | |
|---|
| 214 | instance Functor Node where |
|---|
| 215 | + {-# INLINE fmap #-} |
|---|
| 216 | fmap = fmapDefault |
|---|
| 217 | |
|---|
| 218 | instance Traversable Node where |
|---|
| 219 | hunk ./Data/Sequence.hs 411 |
|---|
| 220 | + {-# INLINE traverse #-} |
|---|
| 221 | traverse f (Node2 v a b) = Node2 v <$> f a <*> f b |
|---|
| 222 | traverse f (Node3 v a b c) = Node3 v <$> f a <*> f b <*> f c |
|---|
| 223 | |
|---|
| 224 | hunk ./Data/Sequence.hs 457 |
|---|
| 225 | showsPrec p (Elem x) = showsPrec p x |
|---|
| 226 | #endif |
|---|
| 227 | |
|---|
| 228 | +------------------------------------------------------- |
|---|
| 229 | +-- Applicative construction |
|---|
| 230 | +------------------------------------------------------- |
|---|
| 231 | + |
|---|
| 232 | +newtype Id a = Id {runId :: a} |
|---|
| 233 | + |
|---|
| 234 | +instance Functor Id where |
|---|
| 235 | + fmap f (Id x) = Id (f x) |
|---|
| 236 | + |
|---|
| 237 | +instance Monad Id where |
|---|
| 238 | + return = Id |
|---|
| 239 | + m >>= k = k (runId m) |
|---|
| 240 | + |
|---|
| 241 | +instance Applicative Id where |
|---|
| 242 | + pure = return |
|---|
| 243 | + (<*>) = ap |
|---|
| 244 | + |
|---|
| 245 | +-- | This is essentially a clone of Control.Monad.State.Strict. |
|---|
| 246 | +newtype State s a = State {runState :: s -> (s, a)} |
|---|
| 247 | + |
|---|
| 248 | +instance Functor (State s) where |
|---|
| 249 | + fmap = liftA |
|---|
| 250 | + |
|---|
| 251 | +instance Monad (State s) where |
|---|
| 252 | + {-# INLINE return #-} |
|---|
| 253 | + {-# INLINE (>>=) #-} |
|---|
| 254 | + return x = State $ \ s -> (s, x) |
|---|
| 255 | + m >>= k = State $ \ s -> case runState m s of |
|---|
| 256 | + (s', x) -> runState (k x) s' |
|---|
| 257 | + |
|---|
| 258 | +instance Applicative (State s) where |
|---|
| 259 | + pure = return |
|---|
| 260 | + (<*>) = ap |
|---|
| 261 | + |
|---|
| 262 | +execState :: State s a -> s -> a |
|---|
| 263 | +execState m x = snd (runState m x) |
|---|
| 264 | + |
|---|
| 265 | +-- | A helper method: a strict version of mapAccumL. |
|---|
| 266 | +mapAccumL' :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c) |
|---|
| 267 | +mapAccumL' f s t = runState (traverse (State . flip f) t) s |
|---|
| 268 | + |
|---|
| 269 | +-- | 'applicativeTree' takes an Applicative-wrapped construction of a piece of a FingerTree, assumed |
|---|
| 270 | +-- to always have the same size (which is put in the second argument), and replicates it as many times |
|---|
| 271 | +-- as specified. This encapsulates the behavior of several procedures, most notably iterate and replicate. |
|---|
| 272 | + |
|---|
| 273 | +{-# SPECIALIZE applicativeTree :: Int -> Int -> State s a -> State s (FingerTree a) #-} |
|---|
| 274 | +{-# SPECIALIZE applicativeTree :: Int -> Int -> Id a -> Id (FingerTree a) #-} |
|---|
| 275 | + -- Special note: the Id specialization automatically does node sharing, reducing memory usage of the |
|---|
| 276 | + -- resulting tree to /O(log n)/. |
|---|
| 277 | +applicativeTree :: Applicative f => Int -> Int -> f a -> f (FingerTree a) |
|---|
| 278 | +applicativeTree n mSize m = mSize `seq` case n of |
|---|
| 279 | + 0 -> pure Empty |
|---|
| 280 | + 1 -> liftA Single m |
|---|
| 281 | + 2 -> deepA one empty one |
|---|
| 282 | + 3 -> deepA two empty one |
|---|
| 283 | + 4 -> deepA two empty two |
|---|
| 284 | + 5 -> deepA three empty two |
|---|
| 285 | + 6 -> deepA three empty three |
|---|
| 286 | + 7 -> deepA four empty three |
|---|
| 287 | + 8 -> deepA four empty four |
|---|
| 288 | + _ -> let (q, r) = n `quotRem` 3 in q `seq` case r of |
|---|
| 289 | + 0 -> deepA three (applicativeTree (q - 2) mSize' n3) three |
|---|
| 290 | + 1 -> deepA four (applicativeTree (q - 2) mSize' n3) three |
|---|
| 291 | + _ -> deepA four (applicativeTree (q - 2) mSize' n3) four |
|---|
| 292 | + where one = liftA One m |
|---|
| 293 | + two = liftA2 Two m m |
|---|
| 294 | + three = liftA3 Three m m m |
|---|
| 295 | + four = liftA3 Four m m m <*> m |
|---|
| 296 | + deepA = liftA3 (Deep (n * mSize)) |
|---|
| 297 | + mSize' = 3 * mSize |
|---|
| 298 | + n3 = liftA3 (Node3 mSize') m m m |
|---|
| 299 | + empty = pure Empty |
|---|
| 300 | + |
|---|
| 301 | ------------------------------------------------------------------------ |
|---|
| 302 | -- Construction |
|---|
| 303 | ------------------------------------------------------------------------ |
|---|
| 304 | hunk ./Data/Sequence.hs 542 |
|---|
| 305 | singleton :: a -> Seq a |
|---|
| 306 | singleton x = Seq (Single (Elem x)) |
|---|
| 307 | |
|---|
| 308 | +-- | /O(log n)/. @replicate n x@ is a sequence of length @n@ with @x@ the value of every element. |
|---|
| 309 | +replicate :: Int -> a -> Seq a |
|---|
| 310 | +replicate n x |
|---|
| 311 | + | n < 0 = error "replicate takes a nonnegative integer argument" |
|---|
| 312 | + | otherwise = Seq (runId (applicativeTree n 1 (Id (Elem x)))) |
|---|
| 313 | + |
|---|
| 314 | -- | /O(1)/. Add an element to the left end of a sequence. |
|---|
| 315 | -- Mnemonic: a triangle with the single element at the pointy end. |
|---|
| 316 | (<|) :: a -> Seq a -> Seq a |
|---|
| 317 | hunk ./Data/Sequence.hs 644 |
|---|
| 318 | appendTree1 xs a Empty = |
|---|
| 319 | xs `snocTree` a |
|---|
| 320 | appendTree1 (Single x) a xs = |
|---|
| 321 | - x `consTree` a `consTree` xs |
|---|
| 322 | + Two x a `consDTree` xs |
|---|
| 323 | appendTree1 xs a (Single x) = |
|---|
| 324 | hunk ./Data/Sequence.hs 646 |
|---|
| 325 | - xs `snocTree` a `snocTree` x |
|---|
| 326 | + xs `snocDTree` Two a x |
|---|
| 327 | appendTree1 (Deep s1 pr1 m1 sf1) a (Deep s2 pr2 m2 sf2) = |
|---|
| 328 | Deep (s1 + size a + s2) pr1 (addDigits1 m1 sf1 a pr2 m2) sf2 |
|---|
| 329 | |
|---|
| 330 | hunk ./Data/Sequence.hs 686 |
|---|
| 331 | |
|---|
| 332 | appendTree2 :: FingerTree (Node a) -> Node a -> Node a -> FingerTree (Node a) -> FingerTree (Node a) |
|---|
| 333 | appendTree2 Empty a b xs = |
|---|
| 334 | - a `consTree` b `consTree` xs |
|---|
| 335 | + Two a b `consDTree` xs |
|---|
| 336 | appendTree2 xs a b Empty = |
|---|
| 337 | hunk ./Data/Sequence.hs 688 |
|---|
| 338 | - xs `snocTree` a `snocTree` b |
|---|
| 339 | + xs `snocDTree` Two a b |
|---|
| 340 | appendTree2 (Single x) a b xs = |
|---|
| 341 | hunk ./Data/Sequence.hs 690 |
|---|
| 342 | - x `consTree` a `consTree` b `consTree` xs |
|---|
| 343 | + Three x a b `consDTree` xs |
|---|
| 344 | appendTree2 xs a b (Single x) = |
|---|
| 345 | hunk ./Data/Sequence.hs 692 |
|---|
| 346 | - xs `snocTree` a `snocTree` b `snocTree` x |
|---|
| 347 | + xs `snocDTree` Three a b x |
|---|
| 348 | appendTree2 (Deep s1 pr1 m1 sf1) a b (Deep s2 pr2 m2 sf2) = |
|---|
| 349 | Deep (s1 + size a + size b + s2) pr1 (addDigits2 m1 sf1 a b pr2 m2) sf2 |
|---|
| 350 | |
|---|
| 351 | hunk ./Data/Sequence.hs 732 |
|---|
| 352 | |
|---|
| 353 | appendTree3 :: FingerTree (Node a) -> Node a -> Node a -> Node a -> FingerTree (Node a) -> FingerTree (Node a) |
|---|
| 354 | appendTree3 Empty a b c xs = |
|---|
| 355 | - a `consTree` b `consTree` c `consTree` xs |
|---|
| 356 | + Three a b c `consDTree` xs |
|---|
| 357 | appendTree3 xs a b c Empty = |
|---|
| 358 | hunk ./Data/Sequence.hs 734 |
|---|
| 359 | - xs `snocTree` a `snocTree` b `snocTree` c |
|---|
| 360 | + xs `snocDTree` Three a b c |
|---|
| 361 | appendTree3 (Single x) a b c xs = |
|---|
| 362 | hunk ./Data/Sequence.hs 736 |
|---|
| 363 | - x `consTree` a `consTree` b `consTree` c `consTree` xs |
|---|
| 364 | + Four x a b c `consDTree` xs |
|---|
| 365 | appendTree3 xs a b c (Single x) = |
|---|
| 366 | hunk ./Data/Sequence.hs 738 |
|---|
| 367 | - xs `snocTree` a `snocTree` b `snocTree` c `snocTree` x |
|---|
| 368 | + xs `snocDTree` Four a b c x |
|---|
| 369 | appendTree3 (Deep s1 pr1 m1 sf1) a b c (Deep s2 pr2 m2 sf2) = |
|---|
| 370 | Deep (s1 + size a + size b + size c + s2) pr1 (addDigits3 m1 sf1 a b c pr2 m2) sf2 |
|---|
| 371 | |
|---|
| 372 | hunk ./Data/Sequence.hs 778 |
|---|
| 373 | |
|---|
| 374 | appendTree4 :: FingerTree (Node a) -> Node a -> Node a -> Node a -> Node a -> FingerTree (Node a) -> FingerTree (Node a) |
|---|
| 375 | appendTree4 Empty a b c d xs = |
|---|
| 376 | - a `consTree` b `consTree` c `consTree` d `consTree` xs |
|---|
| 377 | + Four a b c d `consDTree` xs |
|---|
| 378 | appendTree4 xs a b c d Empty = |
|---|
| 379 | hunk ./Data/Sequence.hs 780 |
|---|
| 380 | - xs `snocTree` a `snocTree` b `snocTree` c `snocTree` d |
|---|
| 381 | + xs `snocDTree` Four a b c d |
|---|
| 382 | appendTree4 (Single x) a b c d xs = |
|---|
| 383 | hunk ./Data/Sequence.hs 782 |
|---|
| 384 | - x `consTree` a `consTree` b `consTree` c `consTree` d `consTree` xs |
|---|
| 385 | + x `consTree` Four a b c d `consDTree` xs |
|---|
| 386 | appendTree4 xs a b c d (Single x) = |
|---|
| 387 | hunk ./Data/Sequence.hs 784 |
|---|
| 388 | - xs `snocTree` a `snocTree` b `snocTree` c `snocTree` d `snocTree` x |
|---|
| 389 | + xs `snocDTree` Four a b c d `snocTree` x |
|---|
| 390 | appendTree4 (Deep s1 pr1 m1 sf1) a b c d (Deep s2 pr2 m2 sf2) = |
|---|
| 391 | Deep (s1 + size a + size b + size c + size d + s2) pr1 (addDigits4 m1 sf1 a b c d pr2 m2) sf2 |
|---|
| 392 | |
|---|
| 393 | hunk ./Data/Sequence.hs 822 |
|---|
| 394 | addDigits4 m1 (Four a b c d) e f g h (Four i j k l) m2 = |
|---|
| 395 | appendTree4 m1 (node3 a b c) (node3 d e f) (node3 g h i) (node3 j k l) m2 |
|---|
| 396 | |
|---|
| 397 | +{-# INLINE consDTree #-} |
|---|
| 398 | +-- Cons an entire digit to a tree. |
|---|
| 399 | +consDTree :: Sized a => Digit a -> FingerTree a -> FingerTree a |
|---|
| 400 | +consDTree dig t = foldr consTree t dig |
|---|
| 401 | + |
|---|
| 402 | +{-# INLINE snocDTree #-} |
|---|
| 403 | +-- Snoc and entire digit to a tree. |
|---|
| 404 | +snocDTree :: Sized a => FingerTree a -> Digit a -> FingerTree a |
|---|
| 405 | +snocDTree t dig = foldl snocTree t dig |
|---|
| 406 | + |
|---|
| 407 | +-- | 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./ |
|---|
| 408 | +unfoldr :: (b -> Maybe (a, b)) -> b -> Seq a |
|---|
| 409 | +unfoldr f b = unfoldr' empty b where |
|---|
| 410 | + -- uses tail recursion rather than, for instance, the List implementation. |
|---|
| 411 | + unfoldr' as b = maybe as (\ (a, b') -> unfoldr' (as |> a) b') (f b) |
|---|
| 412 | + |
|---|
| 413 | +-- | @'unfoldl' f x@ is equivalent to @'reverse' ('unfoldr' f x)@. |
|---|
| 414 | +unfoldl :: (b -> Maybe (b, a)) -> b -> Seq a |
|---|
| 415 | +unfoldl f b = unfoldl' empty b where |
|---|
| 416 | + unfoldl' as b = maybe as (\ (b', a) -> unfoldl' (a <| as) b') (f b) |
|---|
| 417 | + |
|---|
| 418 | +-- | /O(n)/. Constructs a sequence by repeated application of a function to a seed value. |
|---|
| 419 | +-- |
|---|
| 420 | +-- > iterateN n f x = fromList (Prelude.take n (Prelude.iterate f x)) |
|---|
| 421 | +iterateN :: Int -> (a -> a) -> a -> Seq a |
|---|
| 422 | +iterateN n f x |
|---|
| 423 | + | n < 0 = error "iterateN takes a nonnegative integer argument" |
|---|
| 424 | + | otherwise = Seq (execState (applicativeTree n 1 run) x) |
|---|
| 425 | + where run = State $ \ x -> (f x, Elem x) |
|---|
| 426 | + |
|---|
| 427 | ------------------------------------------------------------------------ |
|---|
| 428 | -- Deconstruction |
|---|
| 429 | ------------------------------------------------------------------------ |
|---|
| 430 | hunk ./Data/Sequence.hs 917 |
|---|
| 431 | viewLTree :: Sized a => FingerTree a -> Maybe2 a (FingerTree a) |
|---|
| 432 | viewLTree Empty = Nothing2 |
|---|
| 433 | viewLTree (Single a) = Just2 a Empty |
|---|
| 434 | -viewLTree (Deep s (One a) m sf) = Just2 a (case viewLTree m of |
|---|
| 435 | - Nothing2 -> digitToTree sf |
|---|
| 436 | - Just2 b m' -> Deep (s - size a) (nodeToDigit b) m' sf) |
|---|
| 437 | +viewLTree (Deep s (One a) m sf) = Just2 a (pullL (s - size a) m sf) |
|---|
| 438 | viewLTree (Deep s (Two a b) m sf) = |
|---|
| 439 | Just2 a (Deep (s - size a) (One b) m sf) |
|---|
| 440 | viewLTree (Deep s (Three a b c) m sf) = |
|---|
| 441 | hunk ./Data/Sequence.hs 954 |
|---|
| 442 | foldr f z (xs :> x) = foldr f (f x z) xs |
|---|
| 443 | |
|---|
| 444 | foldl _ z EmptyR = z |
|---|
| 445 | - foldl f z (xs :> x) = f (foldl f z xs) x |
|---|
| 446 | + foldl f z (xs :> x) = foldl f z xs `f` x |
|---|
| 447 | |
|---|
| 448 | foldr1 _ EmptyR = error "foldr1: empty view" |
|---|
| 449 | foldr1 f (xs :> x) = foldr f x xs |
|---|
| 450 | hunk ./Data/Sequence.hs 974 |
|---|
| 451 | viewRTree :: Sized a => FingerTree a -> Maybe2 (FingerTree a) a |
|---|
| 452 | viewRTree Empty = Nothing2 |
|---|
| 453 | viewRTree (Single z) = Just2 Empty z |
|---|
| 454 | -viewRTree (Deep s pr m (One z)) = Just2 (case viewRTree m of |
|---|
| 455 | - Nothing2 -> digitToTree pr |
|---|
| 456 | - Just2 m' y -> Deep (s - size z) pr m' (nodeToDigit y)) z |
|---|
| 457 | +viewRTree (Deep s pr m (One z)) = Just2 (pullR (s - size z) pr m) z |
|---|
| 458 | viewRTree (Deep s pr m (Two y z)) = |
|---|
| 459 | Just2 (Deep (s - size z) pr m (One y)) z |
|---|
| 460 | viewRTree (Deep s pr m (Three x y z)) = |
|---|
| 461 | hunk ./Data/Sequence.hs 982 |
|---|
| 462 | viewRTree (Deep s pr m (Four w x y z)) = |
|---|
| 463 | Just2 (Deep (s - size z) pr m (Three w x y)) z |
|---|
| 464 | |
|---|
| 465 | +------------------------------------------------------------------------ |
|---|
| 466 | +-- Scans |
|---|
| 467 | +-- |
|---|
| 468 | +-- These are not particularly complex applications of the Traversable |
|---|
| 469 | +-- functor, though making the correspondence with Data.List exact |
|---|
| 470 | +-- requires the use of (<|) and (|>). |
|---|
| 471 | +-- |
|---|
| 472 | +-- Note that save for the single (<|) or (|>), we maintain the original |
|---|
| 473 | +-- structure of the Seq, not having to do any restructuring of our own. |
|---|
| 474 | +-- |
|---|
| 475 | +-- wasserman.louis@gmail.com, 5/23/09 |
|---|
| 476 | +------------------------------------------------------------------------ |
|---|
| 477 | + |
|---|
| 478 | +-- | 'scanl' is similar to 'foldl', but returns a sequence of reduced values from the left: |
|---|
| 479 | +-- |
|---|
| 480 | +-- > scanl f z (fromList [x1, x2, ...]) = fromList [z, z `f` x1, (z `f` x1) `f` x2, ...] |
|---|
| 481 | +scanl :: (a -> b -> a) -> a -> Seq b -> Seq a |
|---|
| 482 | +scanl f z0 xs = z0 <| snd (mapAccumL (\ x z -> let x' = f x z in (x', x')) z0 xs) |
|---|
| 483 | + |
|---|
| 484 | +-- | 'scanl1' is a variant of 'scanl' that has no starting value argument: |
|---|
| 485 | +-- |
|---|
| 486 | +-- > scanl1 f (fromList [x1, x2, ...]) = fromList [x1, x1 `f` x2, ...] |
|---|
| 487 | +scanl1 :: (a -> a -> a) -> Seq a -> Seq a |
|---|
| 488 | +scanl1 f xs = case viewl xs of |
|---|
| 489 | + EmptyL -> error "scanl1 takes a nonempty sequence as an argument" |
|---|
| 490 | + x :< xs' -> scanl f x xs' |
|---|
| 491 | + |
|---|
| 492 | +-- | 'scanr' is the right-to-left dual of 'scanl'. |
|---|
| 493 | +scanr :: (a -> b -> b) -> b -> Seq a -> Seq b |
|---|
| 494 | +scanr f z0 xs = snd (mapAccumR (\ z x -> let z' = f x z in (z', z')) z0 xs) |> z0 |
|---|
| 495 | + |
|---|
| 496 | +-- | 'scanr1' is a variant of 'scanr' that has no starting value argument. |
|---|
| 497 | +scanr1 :: (a -> a -> a) -> Seq a -> Seq a |
|---|
| 498 | +scanr1 f xs = case viewr xs of |
|---|
| 499 | + EmptyR -> error "scanr1 takes a nonempty sequence as an argument" |
|---|
| 500 | + xs' :> x -> scanr f x xs' |
|---|
| 501 | + |
|---|
| 502 | -- Indexing |
|---|
| 503 | |
|---|
| 504 | -- | /O(log(min(i,n-i)))/. The element at the specified position, |
|---|
| 505 | hunk ./Data/Sequence.hs 1147 |
|---|
| 506 | sab = sa + size b |
|---|
| 507 | sabc = sab + size c |
|---|
| 508 | |
|---|
| 509 | +-- | A generalization of 'fmap', 'mapWithIndex' takes a mapping function that also depends on the element's |
|---|
| 510 | +-- index, and applies it to every element in the sequence. |
|---|
| 511 | +mapWithIndex :: (Int -> a -> b) -> Seq a -> Seq b |
|---|
| 512 | +mapWithIndex f xs = snd (mapAccumL' (\ i x -> (i + 1, f i x)) 0 xs) |
|---|
| 513 | + |
|---|
| 514 | -- Splitting |
|---|
| 515 | |
|---|
| 516 | -- | /O(log(min(i,n-i)))/. The first @i@ elements of a sequence. |
|---|
| 517 | hunk ./Data/Sequence.hs 1197 |
|---|
| 518 | Split l x r -> Split (maybe Empty digitToTree l) x (deepL r m sf) |
|---|
| 519 | | i < spm = case splitTree im m of |
|---|
| 520 | Split ml xs mr -> case splitNode (im - size ml) xs of |
|---|
| 521 | - Split l x r -> Split (deepR pr ml l) x (deepL r mr sf) |
|---|
| 522 | + Split l x r -> Split (deepR pr ml l) x (deepL r mr sf) |
|---|
| 523 | | otherwise = case splitDigit (i - spm) sf of |
|---|
| 524 | hunk ./Data/Sequence.hs 1199 |
|---|
| 525 | - Split l x r -> Split (deepR pr m l) x (maybe Empty digitToTree r) |
|---|
| 526 | + Split l x r -> Split (deepR pr m l) x (maybe Empty digitToTree r) |
|---|
| 527 | where spr = size pr |
|---|
| 528 | spm = spr + size m |
|---|
| 529 | im = i - spr |
|---|
| 530 | hunk ./Data/Sequence.hs 1204 |
|---|
| 531 | |
|---|
| 532 | -{-# SPECIALIZE deepL :: Maybe (Digit (Elem a)) -> FingerTree (Node (Elem a)) -> Digit (Elem a) -> FingerTree (Elem a) #-} |
|---|
| 533 | -{-# SPECIALIZE deepL :: Maybe (Digit (Node a)) -> FingerTree (Node (Node a)) -> Digit (Node a) -> FingerTree (Node a) #-} |
|---|
| 534 | -deepL :: Sized a => Maybe (Digit a) -> FingerTree (Node a) -> Digit a -> FingerTree a |
|---|
| 535 | -deepL Nothing m sf = case viewLTree m of |
|---|
| 536 | - Nothing2 -> digitToTree sf |
|---|
| 537 | - Just2 a m' -> Deep (size m + size sf) (nodeToDigit a) m' sf |
|---|
| 538 | -deepL (Just pr) m sf = deep pr m sf |
|---|
| 539 | - |
|---|
| 540 | -{-# SPECIALIZE deepR :: Digit (Elem a) -> FingerTree (Node (Elem a)) -> Maybe (Digit (Elem a)) -> FingerTree (Elem a) #-} |
|---|
| 541 | -{-# SPECIALIZE deepR :: Digit (Node a) -> FingerTree (Node (Node a)) -> Maybe (Digit (Node a)) -> FingerTree (Node a) #-} |
|---|
| 542 | -deepR :: Sized a => Digit a -> FingerTree (Node a) -> Maybe (Digit a) -> FingerTree a |
|---|
| 543 | -deepR pr m Nothing = case viewRTree m of |
|---|
| 544 | - Nothing2 -> digitToTree pr |
|---|
| 545 | - Just2 m' a -> Deep (size pr + size m) pr m' (nodeToDigit a) |
|---|
| 546 | -deepR pr m (Just sf) = deep pr m sf |
|---|
| 547 | - |
|---|
| 548 | {-# SPECIALIZE splitNode :: Int -> Node (Elem a) -> Split (Maybe (Digit (Elem a))) (Elem a) #-} |
|---|
| 549 | {-# SPECIALIZE splitNode :: Int -> Node (Node a) -> Split (Maybe (Digit (Node a))) (Node a) #-} |
|---|
| 550 | splitNode :: Sized a => Int -> Node a -> Split (Maybe (Digit a)) a |
|---|
| 551 | hunk ./Data/Sequence.hs 1240 |
|---|
| 552 | where sa = size a |
|---|
| 553 | sab = sa + size b |
|---|
| 554 | sabc = sab + size c |
|---|
| 555 | + |
|---|
| 556 | +-- | /O(n)/. Returns a sequence of all suffixes of this sequence, longest first. For example, |
|---|
| 557 | +-- |
|---|
| 558 | +-- > tails (fromList "abc") = fromList [fromList "abc", fromList "bc", fromList "c", fromList ""] |
|---|
| 559 | +-- |
|---|
| 560 | +-- Evaluating the /i/th suffix takes /O(log(min(i, n-i)))/, but evaluating every suffix in the sequence |
|---|
| 561 | +-- takes /O(n)/ due to sharing. |
|---|
| 562 | +tails :: Seq a -> Seq (Seq a) |
|---|
| 563 | +tails (Seq xs) = Seq (tailsTree (Elem . Seq) xs) |> empty |
|---|
| 564 | + |
|---|
| 565 | +-- | /O(n)/. Returns a sequence of all prefixes of this sequence, shortest first. For example, |
|---|
| 566 | +-- |
|---|
| 567 | +-- > inits (fromList "abc") = fromList [fromList "", fromList "a", fromList "ab", fromList "abc"] |
|---|
| 568 | +-- |
|---|
| 569 | +-- Evaluating the /i/th prefix takes /O(log(min(i, n-i)))/, but evaluating every prefix in the sequence |
|---|
| 570 | +-- takes /O(n)/ due to sharing. |
|---|
| 571 | +inits :: Seq a -> Seq (Seq a) |
|---|
| 572 | +inits (Seq xs) = empty <| Seq (initsTree (Elem . Seq) xs) |
|---|
| 573 | + |
|---|
| 574 | +-- This implementation of tails (and, analogously, inits) has the following algorithmic advantages: |
|---|
| 575 | +-- Evaluating each tail in the sequence takes linear total time, which is better than we could say for |
|---|
| 576 | +-- @fromList [drop n xs | n <- [0..length xs]]@. |
|---|
| 577 | +-- Evaluating any individual tail takes logarithmic time, which is better than we can say for either |
|---|
| 578 | +-- @scanr (<|) empty xs@ or @iterateN (length xs + 1) (\ xs -> let _ :< xs' = viewl xs in xs') xs@. |
|---|
| 579 | +-- |
|---|
| 580 | +-- Moreover, if we actually look at every tail in the sequence, the following benchmarks demonstrate that |
|---|
| 581 | +-- this implementation is modestly faster than any of the above: |
|---|
| 582 | +-- |
|---|
| 583 | +-- Times (ms) |
|---|
| 584 | +-- min mean +/-sd median max |
|---|
| 585 | +-- Seq.tails: 23.022 24.815 3.857 23.508 47.535 |
|---|
| 586 | +-- scanr: 88.141 92.531 6.431 89.298 116.264 |
|---|
| 587 | +-- iterateN: 30.747 31.210 0.320 31.181 32.301 |
|---|
| 588 | +-- |
|---|
| 589 | +-- The algorithm for tails (and, analogously, inits) is as follows: |
|---|
| 590 | +-- |
|---|
| 591 | +-- A Node in the FingerTree of tails is constructed by evaluating the corresponding tail of the FingerTree |
|---|
| 592 | +-- of Nodes, considering the first Node in this tail, and constructing a Node in which each tail of this |
|---|
| 593 | +-- Node is made to be the prefix of the remaining tree. This ends up working quite elegantly, as the remainder of |
|---|
| 594 | +-- the tail of the FingerTree of Nodes becomes the middle of a new tail, the suffix of the Node is the |
|---|
| 595 | +-- prefix, and the suffix of the original tree is retained. |
|---|
| 596 | +-- |
|---|
| 597 | +-- In particular, evaluating the /i/th tail involves making as many partial evaluations as the Node depth of |
|---|
| 598 | +-- the /i/th element. In addition, when we evaluate the /i/th tail, and we also evaluate the /j/th tail, |
|---|
| 599 | +-- and /m/ Nodes are on the path to both /i/ and /j/, each of those /m/ evaluations are shared between |
|---|
| 600 | +-- the computation of the /i/th and /j/th tails. |
|---|
| 601 | +-- |
|---|
| 602 | +-- wasserman.louis@gmail.com, 7/16/09 |
|---|
| 603 | + |
|---|
| 604 | +{-# INLINE scanlSize #-} |
|---|
| 605 | +scanlSize :: (Traversable f, Sized a) => (b -> Int -> b) -> b -> f a -> f b |
|---|
| 606 | +scanlSize f z d = snd (mapAccumL (\ acc x -> let ans = f acc (size x) in (ans, ans)) z d) |
|---|
| 607 | + |
|---|
| 608 | +{-# INLINE scanrSize #-} |
|---|
| 609 | +scanrSize :: (Traversable f, Sized a) => (Int -> b -> b) -> b -> f a -> f b |
|---|
| 610 | +scanrSize f z d = snd (mapAccumR (\ acc x -> let ans = size x `f` acc in (ans, ans)) z d) |
|---|
| 611 | + |
|---|
| 612 | +{-# INLINE zipDigit #-} |
|---|
| 613 | +zipDigit :: (a -> b -> c) -> Digit a -> Digit b -> Digit c |
|---|
| 614 | +zipDigit f (One a) n@(One x) |
|---|
| 615 | + = foldr seq (One (f a x)) n |
|---|
| 616 | +zipDigit f (Two a b) n@(Two x y) |
|---|
| 617 | + = foldr seq (Two (f a x) (f b y)) n |
|---|
| 618 | +zipDigit f (Three a b c) n@(Three x y z) |
|---|
| 619 | + = foldr seq (Three (f a x) (f b y) (f c z)) n |
|---|
| 620 | +zipDigit f (Four a b c d) n@(Four x y z w) |
|---|
| 621 | + = foldr seq (Four (f a x) (f b y) (f c z) (f d w)) n |
|---|
| 622 | +zipDigit _ _ _ = undefined |
|---|
| 623 | + |
|---|
| 624 | +tailsDigit :: Digit a -> Digit (Digit a) |
|---|
| 625 | +tailsDigit (One a) = One (One a) |
|---|
| 626 | +tailsDigit (Two a b) = Two (Two a b) (One b) |
|---|
| 627 | +tailsDigit (Three a b c) = Three (Three a b c) (Two b c) (One c) |
|---|
| 628 | +tailsDigit (Four a b c d) = Four (Four a b c d) (Three b c d) (Two c d) (One d) |
|---|
| 629 | + |
|---|
| 630 | +initsDigit :: Digit a -> Digit (Digit a) |
|---|
| 631 | +initsDigit (One a) = One (One a) |
|---|
| 632 | +initsDigit (Two a b) = Two (One a) (Two a b) |
|---|
| 633 | +initsDigit (Three a b c) = Three (One a) (Two a b) (Three a b c) |
|---|
| 634 | +initsDigit (Four a b c d) = Four (One a) (Two a b) (Three a b c) (Four a b c d) |
|---|
| 635 | + |
|---|
| 636 | +-- Assumes that the two nodes are the same size. |
|---|
| 637 | +zipNode :: (a -> b -> c) -> Node a -> Node b -> Node c |
|---|
| 638 | +zipNode f (Node2 s a b) n@(Node2 _ x y) = foldr seq (Node2 s (f a x) (f b y)) n |
|---|
| 639 | +zipNode f (Node3 s a b c) n@(Node3 _ x y z) = foldr seq (Node3 s (f a x) (f b y) (f c z)) n |
|---|
| 640 | +zipNode _ _ _ = undefined |
|---|
| 641 | + |
|---|
| 642 | +tailsNode :: Node a -> Node (Digit a) |
|---|
| 643 | +tailsNode (Node2 s a b) = Node2 s (Two a b) (One b) |
|---|
| 644 | +tailsNode (Node3 s a b c) = Node3 s (Three a b c) (Two b c) (One c) |
|---|
| 645 | + |
|---|
| 646 | +initsNode :: Node a -> Node (Digit a) |
|---|
| 647 | +initsNode (Node2 s a b) = Node2 s (One a) (Two a b) |
|---|
| 648 | +initsNode (Node3 s a b c) = Node3 s (One a) (Two a b) (Three a b c) |
|---|
| 649 | + |
|---|
| 650 | +{-# SPECIALIZE tailsTree :: (FingerTree (Elem a) -> Elem b) -> FingerTree (Elem a) -> FingerTree (Elem b) #-} |
|---|
| 651 | +{-# SPECIALIZE tailsTree :: (FingerTree (Node a) -> Node b) -> FingerTree (Node a) -> FingerTree (Node b) #-} |
|---|
| 652 | +-- | Given a function to apply to tails of a tree, applies that function to every tail of the specified tree. |
|---|
| 653 | +tailsTree :: (Sized a, Sized b) => (FingerTree a -> b) -> FingerTree a -> FingerTree b |
|---|
| 654 | +tailsTree _ Empty = Empty |
|---|
| 655 | +tailsTree f (Single x) = Single (f (Single x)) |
|---|
| 656 | +tailsTree f (Deep n pr m sf) = |
|---|
| 657 | + Deep n (fmap f $ zipDigit (withPr m) (tailsDigit pr) (scanlSize (-) n pr)) |
|---|
| 658 | + (tailsTree (f' $! size sf) m) |
|---|
| 659 | + (fmap f $ zipDigit (flip digitToTree') (tailsDigit sf) (scanrSize (+) 0 sf)) |
|---|
| 660 | + where withPr m pr sz = Deep sz pr m sf |
|---|
| 661 | + f' sfSize ms = let Just2 node m' = viewLTree ms in |
|---|
| 662 | + fmap f $! zipNode (withPr m') (tailsNode node) (scanrSize (+) (size m' + sfSize) node) |
|---|
| 663 | + |
|---|
| 664 | +{-# SPECIALIZE initsTree :: (FingerTree (Elem a) -> Elem b) -> FingerTree (Elem a) -> FingerTree (Elem b) #-} |
|---|
| 665 | +{-# SPECIALIZE initsTree :: (FingerTree (Node a) -> Node b) -> FingerTree (Node a) -> FingerTree (Node b) #-} |
|---|
| 666 | +-- | Given a function to apply to inits of a tree, applies that function to every init of the specified tree. |
|---|
| 667 | +initsTree :: (Sized a, Sized b) => (FingerTree a -> b) -> FingerTree a -> FingerTree b |
|---|
| 668 | +initsTree _ Empty = Empty |
|---|
| 669 | +initsTree f (Single x) = Single (f (Single x)) |
|---|
| 670 | +initsTree f (Deep n pr m sf) = |
|---|
| 671 | + Deep n (fmap f $ zipDigit (flip digitToTree') (initsDigit pr) (scanlSize (+) 0 pr)) |
|---|
| 672 | + (initsTree (f' $! size pr) m) |
|---|
| 673 | + (fmap f $ zipDigit (withSf m) (initsDigit sf) (scanrSize subtract n sf)) |
|---|
| 674 | + where withSf m sf sz = Deep sz pr m sf |
|---|
| 675 | + f' prSize ms = let Just2 m' node = viewRTree ms in |
|---|
| 676 | + fmap f $! zipNode (withSf m') (initsNode node) (scanlSize (+) (prSize + size m') node) |
|---|
| 677 | |
|---|
| 678 | hunk ./Data/Sequence.hs 1363 |
|---|
| 679 | +{-# INLINE [1] foldIndices #-} |
|---|
| 680 | +-- | foldIndices encapsulates a common schema of predicate-searching functions. In particular, it |
|---|
| 681 | +-- fold every element satisfying p, from left to right. |
|---|
| 682 | +foldIndices :: (a -> Bool) -> Seq a -> (Int -> b -> b) -> b -> b |
|---|
| 683 | +foldIndices p xs f z0 = |
|---|
| 684 | + foldr (\ x z n -> n `seq` if p x then f n (z (n+1)) else z (n+1)) |
|---|
| 685 | + (const z0) xs 0 |
|---|
| 686 | + |
|---|
| 687 | +{-# INLINE [1] foldIndices' #-} |
|---|
| 688 | +-- | foldIndices' folds in every satisfying value, from right to left. |
|---|
| 689 | +foldIndices' :: (a -> Bool) -> Seq a -> (Int -> b -> b) -> b -> b |
|---|
| 690 | +foldIndices' p xs f z0 = |
|---|
| 691 | + foldl (\ z x n -> n `seq` if p x then f n (z (n-1)) else z (n-1)) |
|---|
| 692 | + (const z0) xs (length xs - 1) |
|---|
| 693 | + |
|---|
| 694 | +{-# INLINE [0] appFI #-} |
|---|
| 695 | +appFI :: (a -> b) -> a -> b |
|---|
| 696 | +appFI = ($) |
|---|
| 697 | + |
|---|
| 698 | +{-# INLINE [0] constFI #-} |
|---|
| 699 | +-- Specialized version of const for foldIndices rule matching. |
|---|
| 700 | +constFI :: (a -> b) -> a -> c -> b |
|---|
| 701 | +constFI = (const.) |
|---|
| 702 | + |
|---|
| 703 | +{-# RULES |
|---|
| 704 | + "foldIndices" forall f p xs g z0 . appFI f (foldIndices p xs (constFI g) z0) = |
|---|
| 705 | + foldIndices p xs (constFI (f . g)) (f z0); |
|---|
| 706 | + "foldIndices'" forall f p xs g z0 . appFI f (foldIndices' p xs (constFI g) z0) = |
|---|
| 707 | + foldIndices' p xs (constFI (f . g)) (f z0); |
|---|
| 708 | + #-} |
|---|
| 709 | + |
|---|
| 710 | +-- | /O(i)/ where /i/ is the prefix length. 'takeWhile', applied to a predicate @p@ and a sequence @xs@, returns the |
|---|
| 711 | +-- longest prefix (possibly empty) of @xs@ of elements that satisfy @p@. |
|---|
| 712 | +takeWhile :: (a -> Bool) -> Seq a -> Seq a |
|---|
| 713 | +takeWhile p = appFI fst . span p |
|---|
| 714 | + |
|---|
| 715 | +-- | /O(i)/ where /i/ is the suffix length. 'takeWhileEnd', applied to a predicate @p@ and a sequence @xs@, returns |
|---|
| 716 | +-- the longest suffix (possibly empty) of @xs@ of elements that satisfy @p@. |
|---|
| 717 | +-- |
|---|
| 718 | +-- @'takeWhileEnd' p xs@ is equivalent to @'reverse' ('takeWhile' p ('reverse' xs))@. |
|---|
| 719 | +takeWhileEnd :: (a -> Bool) -> Seq a -> Seq a |
|---|
| 720 | +takeWhileEnd p = appFI fst . span p |
|---|
| 721 | + |
|---|
| 722 | +-- | /O(i)/ where /i/ is the prefix length. @'dropWhile' p xs@ returns the suffix remaining after @takeWhile p xs@. |
|---|
| 723 | +dropWhile :: (a -> Bool) -> Seq a -> Seq a |
|---|
| 724 | +dropWhile p = appFI snd . span p |
|---|
| 725 | + |
|---|
| 726 | +-- | /O(i)/ where /i/ is the suffix length. @'dropWhileEnd' p xs@ returns the prefix remaining after @takeWhileEnd p xs@. |
|---|
| 727 | +-- |
|---|
| 728 | +-- @'dropWhileEnd' p xs@ is equivalent to @'reverse' ('dropWhile' p ('reverse' xs))@. |
|---|
| 729 | +dropWhileEnd :: (a -> Bool) -> Seq a -> Seq a |
|---|
| 730 | +dropWhileEnd p = appFI snd . spanEnd p |
|---|
| 731 | + |
|---|
| 732 | +{-# INLINE [~1] span #-} |
|---|
| 733 | +-- | /O(i)/ where /i/ is the prefix length. 'span', applied to a predicate @p@ and a sequence @xs@, returns a tuple |
|---|
| 734 | +-- whose first element is the longest prefix (possibly empty) of @xs@ of elements that satisfy @p@ and the second |
|---|
| 735 | +-- element is the remainder of the sequence. |
|---|
| 736 | +span :: (a -> Bool) -> Seq a -> (Seq a, Seq a) |
|---|
| 737 | +span p xs = appFI (maybe (xs, empty) (`splitAt` xs)) (findIndex (not . p) xs) |
|---|
| 738 | + |
|---|
| 739 | +{-# INLINE [~1] spanEnd #-} |
|---|
| 740 | +-- | /O(i)/ where /i/ is the suffix length. 'spanEnd', applied to a predicate @p@ and a sequence @xs@, returns a tuple |
|---|
| 741 | +-- whose /first/ element is the longest /suffix/ (possibly empty) of @xs@ of elements that satisfy @p@ and the second |
|---|
| 742 | +-- element is the remainder of the sequence. |
|---|
| 743 | +spanEnd :: (a -> Bool) -> Seq a -> (Seq a, Seq a) |
|---|
| 744 | +spanEnd p xs = appFI (maybe (xs, empty) (flipPair . (`splitAt` xs))) (findLastIndex (not . p) xs) |
|---|
| 745 | + where flipPair (x, y) = (y, x) |
|---|
| 746 | + |
|---|
| 747 | +-- | /O(i)/ where /i/ is the breakpoint index. 'break', applied to a predicate @p@ and a sequence @xs@, returns a tuple |
|---|
| 748 | +-- whose first element is the longest prefix (possibly empty) of @xs@ of elements that /do not satisfy/ @p@ and the |
|---|
| 749 | +-- second element is the remainder of the sequence. |
|---|
| 750 | +-- |
|---|
| 751 | +-- @'break' p@ is equivalent to @'span' (not . p)@. |
|---|
| 752 | +break :: (a -> Bool) -> Seq a -> (Seq a, Seq a) |
|---|
| 753 | +break p = span (not . p) |
|---|
| 754 | + |
|---|
| 755 | +-- | @'breakEnd' p@ is equivalent to @'spanEnd' (not . p)@. |
|---|
| 756 | +breakEnd :: (a -> Bool) -> Seq a -> (Seq a, Seq a) |
|---|
| 757 | +breakEnd p = spanEnd (not . p) |
|---|
| 758 | + |
|---|
| 759 | +-- | /O(n)/. The 'partition' function takes a predicate @p@ and a sequence @xs@ and returns sequences of those |
|---|
| 760 | +-- elements which do and do not satisfy the predicate. |
|---|
| 761 | +partition :: (a -> Bool) -> Seq a -> (Seq a, Seq a) |
|---|
| 762 | +partition p = foldl part (empty, empty) where |
|---|
| 763 | + part (xs, ys) x = if p x then (xs |> x, ys) else (xs, ys |> x) |
|---|
| 764 | + |
|---|
| 765 | +-- | /O(n)/. The 'filter' function takes a predicate @p@ and a sequence @xs@ and returns a sequence of those |
|---|
| 766 | +-- elements which satisfy the predicate. |
|---|
| 767 | +filter :: (a -> Bool) -> Seq a -> Seq a |
|---|
| 768 | +filter p = foldl (\ xs x -> if p x then xs |> x else xs) empty |
|---|
| 769 | + |
|---|
| 770 | +-- Indexing sequences |
|---|
| 771 | + |
|---|
| 772 | +-- | 'elemIndex' finds the first index of the specified element, if it is present. |
|---|
| 773 | +elemIndex :: Eq a => a -> Seq a -> Maybe Int |
|---|
| 774 | +elemIndex x = findIndex (x ==) |
|---|
| 775 | + |
|---|
| 776 | +-- | 'elemLastIndex' finds the last index of the specified element, if it is present. |
|---|
| 777 | +elemLastIndex :: Eq a => a -> Seq a -> Maybe Int |
|---|
| 778 | +elemLastIndex x = findLastIndex (x ==) |
|---|
| 779 | + |
|---|
| 780 | +{-# INLINE elemIndices #-} |
|---|
| 781 | +-- | 'elemIndices' finds the indices of the specified element, in ascending order. |
|---|
| 782 | +elemIndices :: Eq a => a -> Seq a -> [Int] |
|---|
| 783 | +elemIndices x = findIndices (x ==) |
|---|
| 784 | + |
|---|
| 785 | +{-# INLINE elemIndicesDesc #-} |
|---|
| 786 | +-- | 'elemIndicesDesc' finds the indices of the specified element, in descending order. |
|---|
| 787 | +elemIndicesDesc :: Eq a => a -> Seq a -> [Int] |
|---|
| 788 | +elemIndicesDesc x = findIndicesDesc (x ==) |
|---|
| 789 | + |
|---|
| 790 | +{-# INLINE findIndex #-} |
|---|
| 791 | +-- | @'findIndex' p xs@ finds the index of the first element that satisfies @p@, if any exist. |
|---|
| 792 | +findIndex :: (a -> Bool) -> Seq a -> Maybe Int |
|---|
| 793 | +findIndex p xs = foldIndices p xs (constFI Just) Nothing |
|---|
| 794 | + |
|---|
| 795 | +{-# INLINE findLastIndex #-} |
|---|
| 796 | +-- | @'findLastIndex' p xs@ finds the index of the last element that satisfies @p@, if any exist. |
|---|
| 797 | +findLastIndex :: (a -> Bool) -> Seq a -> Maybe Int |
|---|
| 798 | +findLastIndex p xs = foldIndices' p xs (constFI Just) Nothing |
|---|
| 799 | + |
|---|
| 800 | +{-# INLINE findIndices #-} |
|---|
| 801 | +-- | @'findIndices' p@ finds all indices of elements that satisfy @p@, in ascending order. |
|---|
| 802 | +findIndices :: (a -> Bool) -> Seq a -> [Int] |
|---|
| 803 | +#if __GLASGOW_HASKELL__ |
|---|
| 804 | +findIndices p xs = build (foldIndices p xs) |
|---|
| 805 | +#else |
|---|
| 806 | +findIndices p xs = foldIndices p xs (:) [] |
|---|
| 807 | +#endif |
|---|
| 808 | + |
|---|
| 809 | +{-# INLINE findIndicesDesc #-} |
|---|
| 810 | +-- | @'findIndicesDesc' p@ finds all indices of elements that satisfy @p@, in descending order. |
|---|
| 811 | +findIndicesDesc :: (a -> Bool) -> Seq a -> [Int] |
|---|
| 812 | +#if __GLASGOW_HASKELL__ |
|---|
| 813 | +findIndicesDesc p xs = build (foldIndices' p xs) |
|---|
| 814 | +#else |
|---|
| 815 | +findIndicesDesc p xs = foldIndices' p xs (:) [] |
|---|
| 816 | +#endif |
|---|
| 817 | + |
|---|
| 818 | ------------------------------------------------------------------------ |
|---|
| 819 | -- Lists |
|---|
| 820 | ------------------------------------------------------------------------ |
|---|
| 821 | hunk ./Data/Sequence.hs 1528 |
|---|
| 822 | (reverseTree (reverseNode f) m) |
|---|
| 823 | (reverseDigit f pr) |
|---|
| 824 | |
|---|
| 825 | +{-# INLINE reverseDigit #-} |
|---|
| 826 | reverseDigit :: (a -> a) -> Digit a -> Digit a |
|---|
| 827 | reverseDigit f (One a) = One (f a) |
|---|
| 828 | reverseDigit f (Two a b) = Two (f b) (f a) |
|---|
| 829 | hunk ./Data/Sequence.hs 1539 |
|---|
| 830 | reverseNode f (Node2 s a b) = Node2 s (f b) (f a) |
|---|
| 831 | reverseNode f (Node3 s a b c) = Node3 s (f c) (f b) (f a) |
|---|
| 832 | |
|---|
| 833 | +------------------------------------------------------------------------ |
|---|
| 834 | +-- Zipping |
|---|
| 835 | +------------------------------------------------------------------------ |
|---|
| 836 | + |
|---|
| 837 | +-- | /O(n)/. 'zip' takes two sequences and returns a sequence of corresponding pairs. |
|---|
| 838 | +-- If one input is short, excess elements of the longer sequence are discarded. |
|---|
| 839 | +zip :: Seq a -> Seq b -> Seq (a, b) |
|---|
| 840 | +zip = zipWith (,) |
|---|
| 841 | + |
|---|
| 842 | +-- | /O(n)/. 'zipWith' generalizes 'zip' by zipping with the function given as the first argument, |
|---|
| 843 | +-- instead of a tupling function. For example, @zipWith (+)@ is applied to two sequences to take |
|---|
| 844 | +-- the sequence of corresponding sums. |
|---|
| 845 | +zipWith :: (a -> b -> c) -> Seq a -> Seq b -> Seq c |
|---|
| 846 | +zipWith f xs ys |
|---|
| 847 | + | length xs <= length ys = zipWith' f xs ys |
|---|
| 848 | + | otherwise = zipWith' (flip f) ys xs |
|---|
| 849 | + where zipWith' f xs ys = snd (mapAccumL ((\ (y :< ys) x -> (ys, f x y)) . viewl) ys xs) |
|---|
| 850 | + |
|---|
| 851 | +zip3 :: Seq a -> Seq b -> Seq c -> Seq (a,b,c) |
|---|
| 852 | +zip3 = zipWith3 (,,) |
|---|
| 853 | + |
|---|
| 854 | +zipWith3 :: (a -> b -> c -> d) -> Seq a -> Seq b -> Seq c -> Seq d |
|---|
| 855 | +zipWith3 f s1 s2 s3 = zipWith ($) (zipWith f s1 s2) s3 |
|---|
| 856 | + |
|---|
| 857 | +zip4 :: Seq a -> Seq b -> Seq c -> Seq d -> Seq (a,b,c,d) |
|---|
| 858 | +zip4 = zipWith4 (,,,) |
|---|
| 859 | + |
|---|
| 860 | +zipWith4 :: (a -> b -> c -> d -> e) -> Seq a -> Seq b -> Seq c -> Seq d -> Seq e |
|---|
| 861 | +zipWith4 f s1 s2 s3 s4 = zipWith ($) (zipWith ($) (zipWith f s1 s2) s3) s4 |
|---|
| 862 | + |
|---|
| 863 | +------------------------------------------------------------------------ |
|---|
| 864 | +-- Sorting |
|---|
| 865 | +-- |
|---|
| 866 | +-- sort and sortBy are implemented by simple deforestations of |
|---|
| 867 | +-- \ xs -> fromList2 (length xs) . Data.List.sortBy cmp . toList |
|---|
| 868 | +-- which does not get deforested automatically, it would appear. |
|---|
| 869 | +-- |
|---|
| 870 | +-- Unstable sorting is performed by a heap sort implementation based on pairing heaps. Because the |
|---|
| 871 | +-- internal structure of sequences is quite varied, it is difficult to get blocks of elements of |
|---|
| 872 | +-- roughly the same length, which would improve merge sort performance. Pairing heaps, on the other |
|---|
| 873 | +-- hand, are relatively resistant to the effects of merging heaps of wildly different sizes, as |
|---|
| 874 | +-- guaranteed by its amortized constant-time merge operation. Moreover, extensive use of SpecConstr |
|---|
| 875 | +-- transformations can be done on pairing heaps, especially when we're only constructing them |
|---|
| 876 | +-- to immediately be unrolled. |
|---|
| 877 | +-- |
|---|
| 878 | +-- On purely random sequences of length 50000, with no RTS options, I get the following statistics, |
|---|
| 879 | +-- in which heapsort is about 42.5% faster: |
|---|
| 880 | +-- |
|---|
| 881 | +-- Times (ms) min mean +/-sd median max |
|---|
| 882 | +-- to/from list: 103.802 108.572 7.487 106.436 143.339 |
|---|
| 883 | +-- unstable heapsort: 60.686 62.968 4.275 61.187 79.151 |
|---|
| 884 | +-- |
|---|
| 885 | +-- Heapsort, it would seem, is less of a memory hog than Data.List.sortBy. The gap is narrowed |
|---|
| 886 | +-- when more memory is available, but heapsort still wins, 15% faster, with +RTS -H128m: |
|---|
| 887 | +-- |
|---|
| 888 | +-- Times (ms) min mean +/-sd median max |
|---|
| 889 | +-- to/from list: 42.692 45.074 2.596 44.600 56.601 |
|---|
| 890 | +-- unstable heapsort: 37.100 38.344 3.043 37.715 55.526 |
|---|
| 891 | +-- |
|---|
| 892 | +-- In addition, on strictly increasing sequences the gap is even wider than normal; heapsort is |
|---|
| 893 | +-- 68.5% faster with no RTS options: |
|---|
| 894 | +-- Times (ms) min mean +/-sd median max |
|---|
| 895 | +-- to/from list: 52.236 53.574 1.987 53.034 62.098 |
|---|
| 896 | +-- unstable heapsort: 16.433 16.919 0.931 16.681 21.622 |
|---|
| 897 | +-- |
|---|
| 898 | +-- This may be attributed to the elegant nature of the pairing heap. |
|---|
| 899 | +-- |
|---|
| 900 | +-- wasserman.louis@gmail.com, 7/20/09 |
|---|
| 901 | +------------------------------------------------------------------------ |
|---|
| 902 | + |
|---|
| 903 | +-- | /O(n log n)/. 'sort' sorts the specified 'Seq' by the natural ordering of its elements. The sort is stable. |
|---|
| 904 | +-- If a stable sort is not required, 'unstableSort' can be considerably faster, and in particular uses less memory. |
|---|
| 905 | +sort :: Ord a => Seq a -> Seq a |
|---|
| 906 | +sort = sortBy compare |
|---|
| 907 | + |
|---|
| 908 | +-- | /O(n log n)/. 'sortBy' sorts the specified 'Seq' according to the specified comparator. The sort is stable. |
|---|
| 909 | +-- If a stable sort is not required, 'unstableSortBy' can be considerably faster, and in particular uses less memory. |
|---|
| 910 | +sortBy :: (a -> a -> Ordering) -> Seq a -> Seq a |
|---|
| 911 | +-- fromList . Data.List.sortBy cmp . toList doesn't actually deforest well, so I did so manually and got a moderate |
|---|
| 912 | +-- performance boost. |
|---|
| 913 | +sortBy cmp xs = case foldr (\ x -> ([x]:)) [] xs of |
|---|
| 914 | + [] -> empty |
|---|
| 915 | + ys:yss -> fromList2 (length xs) (merger0 ys yss) |
|---|
| 916 | + where xs@(x:xs1) <> ys@(y:ys1) = case cmp x y of |
|---|
| 917 | + GT -> y:(xs <> ys1) |
|---|
| 918 | + _ -> x:(xs1 <> ys) |
|---|
| 919 | + [] <> ys = ys |
|---|
| 920 | + xs <> [] = xs |
|---|
| 921 | + merger (xs1:xs2:xss) = (xs1 <> xs2) : merger xss |
|---|
| 922 | + merger xss = xss |
|---|
| 923 | + merger0 xs1 (xs2:xss) = merger0 (xs1 <> xs2) (merger xss) |
|---|
| 924 | + merger0 xs [] = xs |
|---|
| 925 | + |
|---|
| 926 | +-- | /O(n log n)/. 'unstableSort' sorts the specified 'Seq' by the natural ordering of its elements, but the sort is not stable. |
|---|
| 927 | +-- This algorithm is frequently faster and uses less memory than 'sort', and performs extremely well -- frequently twice as fast as |
|---|
| 928 | +-- 'sort' -- when the sequence is already nearly sorted. |
|---|
| 929 | +unstableSort :: Ord a => Seq a -> Seq a |
|---|
| 930 | +unstableSort = unstableSortBy compare |
|---|
| 931 | + |
|---|
| 932 | +-- | /O(n log n)/. A generalization of 'unstableSort', 'unstableSortBy' takes an arbitrary comparator and sorts the specified sequence. |
|---|
| 933 | +-- The sort is not stable. This algorithm is frequently faster and uses less memory than 'sortBy', and performs extremely well -- |
|---|
| 934 | +-- frequently twice as fast as 'sortBy' -- when the sequence is already nearly sorted. |
|---|
| 935 | +unstableSortBy :: (a -> a -> Ordering) -> Seq a -> Seq a |
|---|
| 936 | +unstableSortBy cmp (Seq xs) = fromList2 (size xs) $ maybe [] (unrollPQ cmp) $ toPQ cmp (\ (Elem x) -> PQueue x Nil) xs |
|---|
| 937 | + |
|---|
| 938 | +fromList2 :: Int -> [a] -> Seq a |
|---|
| 939 | +-- fromList2, given a list and its length, constructs a completely balanced Seq whose elements are that list |
|---|
| 940 | +-- using the applicativeTree generalization. |
|---|
| 941 | +fromList2 n xs = Seq (execState (applicativeTree n 1 (State (\ (x:xs) -> (xs, Elem x)))) xs) |
|---|
| 942 | + |
|---|
| 943 | +-- | A 'PQueue' is a simple pairing heap. |
|---|
| 944 | +data PQueue e = PQueue e (PQL e) |
|---|
| 945 | +data PQL e = Nil | {-# UNPACK #-} !(PQueue e) :& PQL e |
|---|
| 946 | + |
|---|
| 947 | +infixr 8 :& |
|---|
| 948 | + |
|---|
| 949 | +#if TESTING |
|---|
| 950 | + |
|---|
| 951 | +instance Functor PQueue where |
|---|
| 952 | + fmap f (PQueue x ts) = PQueue (f x) (fmap f ts) |
|---|
| 953 | + |
|---|
| 954 | +instance Functor PQL where |
|---|
| 955 | + fmap f (q :& qs) = fmap f q :& fmap f qs |
|---|
| 956 | + fmap _ Nil = Nil |
|---|
| 957 | + |
|---|
| 958 | +instance Show e => Show (PQueue e) where |
|---|
| 959 | + show = unlines . draw . fmap show |
|---|
| 960 | + |
|---|
| 961 | +-- borrowed wholesale from Data.Tree, as Data.Tree actually depends on Data.Sequence |
|---|
| 962 | +draw :: PQueue String -> [String] |
|---|
| 963 | +draw (PQueue x ts0) = x : drawSubTrees ts0 |
|---|
| 964 | + where drawSubTrees Nil = [] |
|---|
| 965 | + drawSubTrees (t :& Nil) = |
|---|
| 966 | + "|" : shift "`- " " " (draw t) |
|---|
| 967 | + drawSubTrees (t :& ts) = |
|---|
| 968 | + "|" : shift "+- " "| " (draw t) ++ drawSubTrees ts |
|---|
| 969 | + |
|---|
| 970 | + shift first other = Data.List.zipWith (++) (first : repeat other) |
|---|
| 971 | +#endif |
|---|
| 972 | + |
|---|
| 973 | +-- | 'unrollPQ', given a comparator function, unrolls a 'PQueue' into a sorted list. |
|---|
| 974 | +unrollPQ :: (e -> e -> Ordering) -> PQueue e -> [e] |
|---|
| 975 | +unrollPQ cmp = unrollPQ' where |
|---|
| 976 | + {-# INLINE unrollPQ' #-} |
|---|
| 977 | + unrollPQ' (PQueue x ts) = x:mergePQs0 ts |
|---|
| 978 | + (<>) = mergePQ cmp |
|---|
| 979 | + mergePQs0 Nil = [] |
|---|
| 980 | + mergePQs0 (t :& Nil) = unrollPQ' t |
|---|
| 981 | + mergePQs0 (t1 :& t2 :& ts) = mergePQs (t1 <> t2) ts |
|---|
| 982 | + mergePQs t ts = t `seq` case ts of |
|---|
| 983 | + Nil -> unrollPQ' t |
|---|
| 984 | + t1 :& Nil -> unrollPQ' (t <> t1) |
|---|
| 985 | + t1 :& t2 :& ts -> mergePQs (t <> (t1 <> t2)) ts |
|---|
| 986 | + |
|---|
| 987 | +-- | 'toPQ', given an ordering function and a mechanism for queueifying elements, converts a 'FingerTree' to a 'PQueue'. |
|---|
| 988 | +toPQ :: (e -> e -> Ordering) -> (a -> PQueue e) -> FingerTree a -> Maybe (PQueue e) |
|---|
| 989 | +toPQ _ _ Empty = Nothing |
|---|
| 990 | +toPQ _ f (Single x) = Just (f x) |
|---|
| 991 | +toPQ cmp f (Deep _ pr m sf) = Just (maybe (pr' <> sf') ((pr' <> sf') <>) (toPQ cmp fNode m)) where |
|---|
| 992 | + fDigit d = case fmap f d of |
|---|
| 993 | + One a -> a |
|---|
| 994 | + Two a b -> a <> b |
|---|
| 995 | + Three a b c -> a <> b <> c |
|---|
| 996 | + Four a b c d -> (a <> b) <> (c <> d) |
|---|
| 997 | + (<>) = mergePQ cmp |
|---|
| 998 | + fNode = fDigit . nodeToDigit |
|---|
| 999 | + pr' = fDigit pr |
|---|
| 1000 | + sf' = fDigit sf |
|---|
| 1001 | + |
|---|
| 1002 | +-- | 'mergePQ' merges two 'PQueue's. |
|---|
| 1003 | +mergePQ :: (a -> a -> Ordering) -> PQueue a -> PQueue a -> PQueue a |
|---|
| 1004 | +mergePQ cmp q1@(PQueue x1 ts1) q2@(PQueue x2 ts2) |
|---|
| 1005 | + | cmp x1 x2 == GT = PQueue x2 (q1 :& ts2) |
|---|
| 1006 | + | otherwise = PQueue x1 (q2 :& ts1) |
|---|
| 1007 | + |
|---|
| 1008 | #if TESTING |
|---|
| 1009 | |
|---|
| 1010 | ------------------------------------------------------------------------ |
|---|
| 1011 | hunk ./Data/Sequence.hs 1722 |
|---|
| 1012 | |
|---|
| 1013 | instance Arbitrary a => Arbitrary (Seq a) where |
|---|
| 1014 | arbitrary = liftM Seq arbitrary |
|---|
| 1015 | - coarbitrary (Seq x) = coarbitrary x |
|---|
| 1016 | + shrink (Seq x) = map Seq (shrink x) |
|---|
| 1017 | |
|---|
| 1018 | instance Arbitrary a => Arbitrary (Elem a) where |
|---|
| 1019 | arbitrary = liftM Elem arbitrary |
|---|
| 1020 | hunk ./Data/Sequence.hs 1726 |
|---|
| 1021 | - coarbitrary (Elem x) = coarbitrary x |
|---|
| 1022 | |
|---|
| 1023 | instance (Arbitrary a, Sized a) => Arbitrary (FingerTree a) where |
|---|
| 1024 | arbitrary = sized arb |
|---|
| 1025 | hunk ./Data/Sequence.hs 1734 |
|---|
| 1026 | arb 1 = liftM Single arbitrary |
|---|
| 1027 | arb n = liftM3 deep arbitrary (arb (n `div` 2)) arbitrary |
|---|
| 1028 | |
|---|
| 1029 | - coarbitrary Empty = variant 0 |
|---|
| 1030 | - coarbitrary (Single x) = variant 1 . coarbitrary x |
|---|
| 1031 | - coarbitrary (Deep _ pr m sf) = |
|---|
| 1032 | - variant 2 . coarbitrary pr . coarbitrary m . coarbitrary sf |
|---|
| 1033 | + shrink (Deep _ (One a) Empty (One b)) = [Single a, Single b] |
|---|
| 1034 | + shrink (Deep _ pr m sf) = [deep pr' m sf | pr' <- shrink pr] ++ [deep pr m' sf | m' <- shrink m] ++ [deep pr m sf' | sf' <- shrink sf] |
|---|
| 1035 | + shrink (Single x) = map Single (shrink x) |
|---|
| 1036 | + shrink Empty = [] |
|---|
| 1037 | |
|---|
| 1038 | instance (Arbitrary a, Sized a) => Arbitrary (Node a) where |
|---|
| 1039 | arbitrary = oneof [ |
|---|
| 1040 | hunk ./Data/Sequence.hs 1744 |
|---|
| 1041 | liftM2 node2 arbitrary arbitrary, |
|---|
| 1042 | liftM3 node3 arbitrary arbitrary arbitrary] |
|---|
| 1043 | |
|---|
| 1044 | - coarbitrary (Node2 _ a b) = variant 0 . coarbitrary a . coarbitrary b |
|---|
| 1045 | - coarbitrary (Node3 _ a b c) = |
|---|
| 1046 | - variant 1 . coarbitrary a . coarbitrary b . coarbitrary c |
|---|
| 1047 | + shrink (Node2 _ a b) = [node2 a' b | a' <- shrink a] ++ [node2 a b' | b' <- shrink b] |
|---|
| 1048 | + shrink (Node3 _ a b c) = [node2 a b, node2 a c, node2 b c] ++ |
|---|
| 1049 | + [node3 a' b c | a' <- shrink a] ++ [node3 a b' c | b' <- shrink b] ++ [node3 a b c' | c' <- shrink c] |
|---|
| 1050 | |
|---|
| 1051 | instance Arbitrary a => Arbitrary (Digit a) where |
|---|
| 1052 | arbitrary = oneof [ |
|---|
| 1053 | hunk ./Data/Sequence.hs 1754 |
|---|
| 1054 | liftM2 Two arbitrary arbitrary, |
|---|
| 1055 | liftM3 Three arbitrary arbitrary arbitrary, |
|---|
| 1056 | liftM4 Four arbitrary arbitrary arbitrary arbitrary] |
|---|
| 1057 | - |
|---|
| 1058 | - coarbitrary (One a) = variant 0 . coarbitrary a |
|---|
| 1059 | - coarbitrary (Two a b) = variant 1 . coarbitrary a . coarbitrary b |
|---|
| 1060 | - coarbitrary (Three a b c) = |
|---|
| 1061 | - variant 2 . coarbitrary a . coarbitrary b . coarbitrary c |
|---|
| 1062 | - coarbitrary (Four a b c d) = |
|---|
| 1063 | - variant 3 . coarbitrary a . coarbitrary b . coarbitrary c . coarbitrary d |
|---|
| 1064 | + |
|---|
| 1065 | + shrink (One a) = map One (shrink a) |
|---|
| 1066 | + shrink (Two a b) = [One a, One b] |
|---|
| 1067 | + shrink (Three a b c) = [Two a b, Two a c, Two b c] |
|---|
| 1068 | + shrink (Four a b c d) = [Three a b c, Three a b d, Three a c d, Three b c d] |
|---|
| 1069 | |
|---|
| 1070 | ------------------------------------------------------------------------ |
|---|
| 1071 | -- Valid trees |
|---|
| 1072 | hunk ./Data/Sequence.hs 1780 |
|---|
| 1073 | s == size pr + size m + size sf && valid pr && valid m && valid sf |
|---|
| 1074 | |
|---|
| 1075 | instance (Sized a, Valid a) => Valid (Node a) where |
|---|
| 1076 | - valid (Node2 s a b) = s == size a + size b && valid a && valid b |
|---|
| 1077 | - valid (Node3 s a b c) = |
|---|
| 1078 | - s == size a + size b + size c && valid a && valid b && valid c |
|---|
| 1079 | + valid node = (size node == foldl1 (+) (fmap size node)) && (all valid node) |
|---|
| 1080 | |
|---|
| 1081 | instance Valid a => Valid (Digit a) where |
|---|
| 1082 | hunk ./Data/Sequence.hs 1783 |
|---|
| 1083 | - valid (One a) = valid a |
|---|
| 1084 | - valid (Two a b) = valid a && valid b |
|---|
| 1085 | - valid (Three a b c) = valid a && valid b && valid c |
|---|
| 1086 | - valid (Four a b c d) = valid a && valid b && valid c && valid d |
|---|
| 1087 | + valid = all valid |
|---|
| 1088 | |
|---|
| 1089 | #endif |
|---|
| 1090 | hunk ./containers.cabal 23 |
|---|
| 1091 | location: http://darcs.haskell.org/packages/containers/ |
|---|
| 1092 | |
|---|
| 1093 | Library { |
|---|
| 1094 | - build-depends: base, array |
|---|
| 1095 | + build-depends: base >= 4.0.0.0, array |
|---|
| 1096 | exposed-modules: |
|---|
| 1097 | Data.Graph |
|---|
| 1098 | Data.IntMap |
|---|
| 1099 | } |
|---|
| 1100 | |
|---|
| 1101 | Context: |
|---|
| 1102 | |
|---|
| 1103 | [Use left/right rather than old/new to describe the arguments to unionWithKey |
|---|
| 1104 | Ian Lynagh <igloo@earth.li>**20090208192132 |
|---|
| 1105 | Fixes trac #3002. |
|---|
| 1106 | ] |
|---|
| 1107 | [help nhc98 by making import decl more explicit |
|---|
| 1108 | Malcolm.Wallace@cs.york.ac.uk**20090203142144] |
|---|
| 1109 | [Add instance Data.Traversable for IntMap |
|---|
| 1110 | Matti Niemenmaa <matti.niemenmaa+darcs@iki.fi>**20090116190353 |
|---|
| 1111 | Ignore-this: df88a286935926aecec3f8a5dd291699 |
|---|
| 1112 | ] |
|---|
| 1113 | [Require Cabal version >= 1.6 |
|---|
| 1114 | Ian Lynagh <igloo@earth.li>**20090122011256] |
|---|
| 1115 | [Add "bug-reports" and "source-repository" info to the Cabal file |
|---|
| 1116 | Ian Lynagh <igloo@earth.li>**20090121182106] |
|---|
| 1117 | [Fix warnings in containers |
|---|
| 1118 | Ian Lynagh <igloo@earth.li>**20090116200251] |
|---|
| 1119 | [optimize IntMap/IntSet findMin/findMax |
|---|
| 1120 | sedillard@gmail.com**20081002152055] |
|---|
| 1121 | [O(n) fromAscList IntSet / IntMap |
|---|
| 1122 | sedillard@gmail.com**20080521195941 |
|---|
| 1123 | |
|---|
| 1124 | Added algorithm by Scott Dillard and Bertram Felgenhauer to build IntSets and |
|---|
| 1125 | IntMaps from sorted input in linear time. Also changed quickcheck prop_Ordered |
|---|
| 1126 | (no longer a tautology!) to include negative and duplicate keys. |
|---|
| 1127 | |
|---|
| 1128 | ] |
|---|
| 1129 | [correct type for IntMap.intersectionWith[Key] |
|---|
| 1130 | sedillard@gmail.com**20081002144828] |
|---|
| 1131 | [Export mapAccumRWithKey from Map and IntMap (Trac #2769) |
|---|
| 1132 | matti.niemenmaa+darcs@iki.fi**20081210160205] |
|---|
| 1133 | [Bump the version number to 0.2.0.1, to work-around cabal-install problems |
|---|
| 1134 | Ian Lynagh <igloo@earth.li>**20081212201829] |
|---|
| 1135 | [Fix #2760: change mkNorepType to mkNoRepType |
|---|
| 1136 | 'Jose Pedro Magalhaes <jpm@cs.uu.nl>'**20081202083424] |
|---|
| 1137 | [Doc fix, from hackage trac #378 |
|---|
| 1138 | Ian Lynagh <igloo@earth.li>**20081024143949] |
|---|
| 1139 | [import Data.Data instead of Data.Generics.*, eliminating the dependency on syb |
|---|
| 1140 | Ross Paterson <ross@soi.city.ac.uk>**20081005002559] |
|---|
| 1141 | [fixed typo in highestBitMask |
|---|
| 1142 | sedillard@gmail.com**20081002215438] |
|---|
| 1143 | [export Data.Map.toDescList, foldlWithKey, and foldrWithKey (trac ticket 2580) |
|---|
| 1144 | qdunkan@gmail.com**20080922213200 |
|---|
| 1145 | |
|---|
| 1146 | toDescList was previously implemented, but not exported. |
|---|
| 1147 | |
|---|
| 1148 | foldlWithKey was previously implemented, but not exported. It can be used to |
|---|
| 1149 | implement toDescList. |
|---|
| 1150 | |
|---|
| 1151 | foldrWithKey is already exported as foldWithKey, but foldrWithKey is explicitly |
|---|
| 1152 | the mirror of foldlWithKey, and foldWithKey kept for compatibility. |
|---|
| 1153 | ] |
|---|
| 1154 | [Bump version number to 0.2.0.0 |
|---|
| 1155 | Ian Lynagh <igloo@earth.li>**20080920160016] |
|---|
| 1156 | [TAG 6.10 branch has been forked |
|---|
| 1157 | Ian Lynagh <igloo@earth.li>**20080919123438] |
|---|
| 1158 | [Fixed typo in updateMinWithKey / updateMaxWithKey |
|---|
| 1159 | sedillard@gmail.com**20080704054350] |
|---|
| 1160 | [follow library changes |
|---|
| 1161 | Ian Lynagh <igloo@earth.li>**20080903223610] |
|---|
| 1162 | [add include/Typeable.h to extra-source-files |
|---|
| 1163 | Ross Paterson <ross@soi.city.ac.uk>**20080831181402] |
|---|
| 1164 | [fix cabal build-depends for nhc98 |
|---|
| 1165 | Malcolm.Wallace@cs.york.ac.uk**20080828104248] |
|---|
| 1166 | [Add a dep on syb |
|---|
| 1167 | Ian Lynagh <igloo@earth.li>**20080825214314] |
|---|
| 1168 | [add category field |
|---|
| 1169 | Ross Paterson <ross@soi.city.ac.uk>**20080824003013] |
|---|
| 1170 | [we depend on st, now split off from base |
|---|
| 1171 | Ian Lynagh <igloo@earth.li>**20080823223053] |
|---|
| 1172 | [specialize functions that fail in a Monad to Maybe (proposal #2309) |
|---|
| 1173 | Ross Paterson <ross@soi.city.ac.uk>**20080722154812 |
|---|
| 1174 | |
|---|
| 1175 | Specialize functions signatures like |
|---|
| 1176 | |
|---|
| 1177 | lookup :: (Monad m, Ord k) => k -> Map k a -> m a |
|---|
| 1178 | to |
|---|
| 1179 | lookup :: (Ord k) => k -> Map k a -> Maybe a |
|---|
| 1180 | |
|---|
| 1181 | for simplicity and safety. No information is lost, as each of these |
|---|
| 1182 | functions had only one use of fail, which is now changed to Nothing. |
|---|
| 1183 | ] |
|---|
| 1184 | [tighter description of split (addresses #2447) |
|---|
| 1185 | Ross Paterson <ross@soi.city.ac.uk>**20080717064838] |
|---|
| 1186 | [Make warning-clean with GHC again |
|---|
| 1187 | Ian Lynagh <igloo@earth.li>**20080623232023 |
|---|
| 1188 | With any luck we have now converged on a solution that works everywhere! |
|---|
| 1189 | ] |
|---|
| 1190 | [Undo more Data.Typeable-related breakage for non-ghc. |
|---|
| 1191 | Malcolm.Wallace@cs.york.ac.uk**20080623092757] |
|---|
| 1192 | [Placate GHC with explicit import lists |
|---|
| 1193 | Ian Lynagh <igloo@earth.li>**20080620183926] |
|---|
| 1194 | [undo breakage caused by -Wall cleaning |
|---|
| 1195 | Malcolm.Wallace@cs.york.ac.uk**20080620093922 |
|---|
| 1196 | The import of Data.Typeable is still required, at least for non-GHC. |
|---|
| 1197 | ] |
|---|
| 1198 | [Make the package -Wall clean |
|---|
| 1199 | Ian Lynagh <igloo@earth.li>**20080618233627] |
|---|
| 1200 | [List particular extensions rather than -fglasgow-exts |
|---|
| 1201 | Ian Lynagh <igloo@earth.li>**20080616232035] |
|---|
| 1202 | [Avoid using deprecated flags |
|---|
| 1203 | Ian Lynagh <igloo@earth.li>**20080616145241] |
|---|
| 1204 | [TAG 2008-05-28 |
|---|
| 1205 | Ian Lynagh <igloo@earth.li>**20080528004309] |
|---|
| 1206 | Patch bundle hash: |
|---|
| 1207 | 237a4101f4d9bd662e17f7523861d74e8d66097a |
|---|