ralist 0.1.0.0 → 0.2.0.0
raw patch · 4 files changed
+1013/−80 lines, 4 filesdep +criteriondep +deepseqdep +faildep ~basenew-uploaderPVP ok
version bump matches the API change (PVP)
Dependencies added: criterion, deepseq, fail, hspec, ralist, semigroups
Dependency ranges changed: base
API changes (from Hackage documentation)
- Data.RAList: instance Eq a => Eq (RAList a)
- Data.RAList: instance Eq a => Eq (Top a)
- Data.RAList: instance Eq a => Eq (Tree a)
- Data.RAList: instance Functor RAList
- Data.RAList: instance Functor Top
- Data.RAList: instance Functor Tree
- Data.RAList: instance Monad RAList
- Data.RAList: instance Monoid (RAList a)
- Data.RAList: instance Ord a => Ord (RAList a)
- Data.RAList: instance Read a => Read (RAList a)
- Data.RAList: instance Show a => Show (RAList a)
+ Data.RAList: infixl 9 !!
+ Data.RAList: infixr 5 ++
+ Data.RAList: instance Data.Data.Data a => Data.Data.Data (Data.RAList.RAList a)
+ Data.RAList: instance Data.Data.Data a => Data.Data.Data (Data.RAList.Top a)
+ Data.RAList: instance Data.Data.Data a => Data.Data.Data (Data.RAList.Tree a)
+ Data.RAList: instance Data.Foldable.Foldable Data.RAList.RAList
+ Data.RAList: instance Data.Foldable.Foldable Data.RAList.Top
+ Data.RAList: instance Data.Foldable.Foldable Data.RAList.Tree
+ Data.RAList: instance Data.Semigroup.Semigroup (Data.RAList.RAList a)
+ Data.RAList: instance Data.Traversable.Traversable Data.RAList.Top
+ Data.RAList: instance Data.Traversable.Traversable Data.RAList.Tree
+ Data.RAList: instance GHC.Base.Applicative Data.RAList.RAList
+ Data.RAList: instance GHC.Base.Functor Data.RAList.RAList
+ Data.RAList: instance GHC.Base.Functor Data.RAList.Top
+ Data.RAList: instance GHC.Base.Functor Data.RAList.Tree
+ Data.RAList: instance GHC.Base.Monad Data.RAList.RAList
+ Data.RAList: instance GHC.Base.Monoid (Data.RAList.RAList a)
+ Data.RAList: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.RAList.RAList a)
+ Data.RAList: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.RAList.Top a)
+ Data.RAList: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.RAList.Tree a)
+ Data.RAList: instance GHC.Classes.Ord a => GHC.Classes.Ord (Data.RAList.RAList a)
+ Data.RAList: instance GHC.Read.Read a => GHC.Read.Read (Data.RAList.RAList a)
+ Data.RAList: instance GHC.Show.Show a => GHC.Show.Show (Data.RAList.RAList a)
+ Data.RAList: lookupL :: (Eq a) => a -> RAList (a, b) -> Maybe b
+ Data.RAList: lookupM :: forall (m :: * -> *) a. Monad m => Word64 -> Top a -> m a
+ Data.RAList: lookupWithDefault :: forall t. t -> Word64 -> Top t -> t
+ Data.RAList: simpleDrop :: Word64 -> RAList a -> RAList a
+ Data.RAList: uncons :: RAList a -> Maybe (a, RAList a)
- Data.RAList: (!!) :: RAList a -> Int -> a
+ Data.RAList: (!!) :: RAList a -> Word64 -> a
- Data.RAList: adjust :: (a -> a) -> Int -> RAList a -> RAList a
+ Data.RAList: adjust :: (a -> a) -> Word64 -> RAList a -> RAList a
- Data.RAList: drop :: Int -> RAList a -> RAList a
+ Data.RAList: drop :: Word64 -> RAList a -> RAList a
- Data.RAList: elem :: Eq a => a -> RAList a -> Bool
+ Data.RAList: elem :: (Eq a) => a -> RAList a -> Bool
- Data.RAList: head :: RAList a -> a
+ Data.RAList: head :: RAList a -> Maybe a
- Data.RAList: length :: RAList a -> Int
+ Data.RAList: length :: RAList a -> Word64
- Data.RAList: lookup :: Eq a => a -> RAList (a, b) -> Maybe b
+ Data.RAList: lookup :: forall a. Word64 -> Top a -> a
- Data.RAList: maximum :: Ord a => RAList a -> a
+ Data.RAList: maximum :: (Ord a) => RAList a -> a
- Data.RAList: minimum :: Ord a => RAList a -> a
+ Data.RAList: minimum :: (Ord a) => RAList a -> a
- Data.RAList: notElem :: Eq a => a -> RAList a -> Bool
+ Data.RAList: notElem :: (Eq a) => a -> RAList a -> Bool
- Data.RAList: product :: Num a => RAList a -> a
+ Data.RAList: product :: (Num a) => RAList a -> a
- Data.RAList: replicate :: Int -> a -> RAList a
+ Data.RAList: replicate :: Word64 -> a -> RAList a
- Data.RAList: splitAt :: Int -> RAList a -> (RAList a, RAList a)
+ Data.RAList: splitAt :: Word64 -> RAList a -> (RAList a, RAList a)
- Data.RAList: sum :: Num a => RAList a -> a
+ Data.RAList: sum :: (Num a) => RAList a -> a
- Data.RAList: tail :: RAList a -> RAList a
+ Data.RAList: tail :: RAList a -> Maybe (RAList a)
- Data.RAList: take :: Int -> RAList a -> RAList a
+ Data.RAList: take :: Word64 -> RAList a -> RAList a
- Data.RAList: update :: Int -> a -> RAList a -> RAList a
+ Data.RAList: update :: Word64 -> a -> RAList a -> RAList a
Files
- Data/RAList.hs +188/−76
- benchmark/benchmarking.hs +63/−0
- ralist.cabal +54/−4
- tests/hspec.hs +708/−0
Data/RAList.hs view
@@ -1,4 +1,10 @@--- | +{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE ExplicitForAll #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE DeriveFoldable , DeriveTraversable#-}+-- | -- A random-access list implementation based on Chris Okasaki's approach -- on his book \"Purely Functional Data Structures\", Cambridge University -- Press, 1998, chapter 9.3.@@ -13,9 +19,9 @@ RAList -- * Basic functions- , empty , cons+ , uncons -- , singleton , (++) , head@@ -25,6 +31,20 @@ , null , length + -- * Indexing lists+ -- | These functions treat a list @xs@ as a indexed collection,+ -- with indices ranging from 0 to @'length' xs - 1@.++ , (!!)+ ,lookupWithDefault+ ,lookupM+ ,lookup++ --- * KV indexing+ --- | This function treats a RAList as an association list+ ,lookupL++ -- * List transformations , map , reverse@@ -32,7 +52,7 @@ , intersperse , intercalate , transpose- + , subsequences , permutations @@ -83,6 +103,7 @@ -- ** Extracting sublists , take , drop+ , simpleDrop , splitAt {-RA @@ -109,18 +130,14 @@ -- ** Searching by equality , elem , notElem- , lookup+ {-RA -- ** Searching with a predicate , find -} , filter , partition- -- * Indexing lists- -- | These functions treat a list @xs@ as a indexed collection,- -- with indices ranging from 0 to @'length' xs - 1@. - , (!!) {-RA , elemIndex , elemIndices@@ -214,8 +231,13 @@ zip, zipWith, unzip ) import qualified Data.List as List-import Data.Monoid-+#if !MIN_VERSION_base(4,9,0) == 1+import Data.Monoid(Monoid,mappend,mempty)+#endif+import Data.Semigroup(Semigroup,(<>))+import Data.Data(Data,Typeable)+import Data.Functor.Identity(runIdentity)+import Data.Word infixl 9 !! infixr 5 `cons`, ++@@ -227,8 +249,8 @@ -- [ [], [1], [1,1], [3], [1,3], [1,1,3], [3,3], [7], [1,7], [1,1,7], -- [3,7], [1,3,7], [1,1,3,7], [3,3,7], [7,7], [15], ... -- (I.e., skew binary numbers.)-data RAList a = RAList {-# UNPACK #-} !Int !(Top a)- deriving (Eq)+data RAList a = RAList {-# UNPACK #-} !Word64 !(Top a)+ deriving (Eq,Data,Typeable,Foldable) instance (Show a) => Show (RAList a) where showsPrec p xs = showParen (p >= 10) $ showString "fromList " . showsPrec 10 (toList xs)@@ -245,33 +267,40 @@ instance Monoid (RAList a) where mempty = empty- mappend = (++)+ mappend = (<>) +instance Semigroup (RAList a) where+ (<>) = (++)+ instance Functor RAList where fmap f (RAList s wts) = RAList s (fmap f wts) +instance Applicative RAList where+ pure = \x -> RAList 1 (Cons 1 (Leaf x) Nil)+ (<*>) = zipWith ($)+ instance Monad RAList where- return x = RAList 1 (Cons 1 (Leaf x) Nil)+ return = pure (>>=) = flip concatMap --- Special list type for (Int, Tree a), i.e., Top a ~= [(Int, Tree a)]-data Top a = Nil | Cons {-# UNPACK #-} !Int !(Tree a) (Top a)- deriving (Eq)+-- Special list type for (Word64, Tree a), i.e., Top a ~= [(Word64, Tree a)]+data Top a = Nil | Cons {-# UNPACK #-} !Word64 !(Tree a) (Top a)+ deriving (Eq,Data,Typeable,Functor,Foldable,Traversable) -instance Functor Top where- fmap _ Nil = Nil- fmap f (Cons w t xs) = Cons w (fmap f t) (fmap f xs)+--instance Functor Top where+-- fmap _ Nil = Nil+-- fmap f (Cons w t xs) = Cons w (fmap f t) (fmap f xs) -- Complete binary tree. The completeness of the trees is an invariant that must -- be preserved for the implementation to work. data Tree a = Leaf a | Node a !(Tree a) !(Tree a)- deriving (Eq)+ deriving (Eq,Data,Typeable,Functor,Foldable,Traversable) -instance Functor Tree where- fmap f (Leaf x) = Leaf (f x)- fmap f (Node x l r) = Node (f x) (fmap f l) (fmap f r)+--instance Functor Tree where+-- fmap f (Leaf x) = Leaf (f x)+-- fmap f (Node x l r) = Node (f x) (fmap f l) (fmap f r) ----- @@ -289,23 +318,78 @@ xs ++ ys | null ys = xs -- small optimization to avoid consing to empty | otherwise = foldr cons ys xs ++uncons :: RAList a -> Maybe (a, RAList a)+uncons (RAList _ Nil) = Nothing+uncons (RAList s (Cons _ (Leaf h) wts)) = Just (h,RAList (s-1) wts)+uncons (RAList s (Cons w (Node x l r) wts)) = Just (x, RAList (s-1) (Cons w2 l (Cons w2 r wts)))+ where w2 = w `quot` 2+ -- | Complexity /O(1)/.-head :: RAList a -> a-head (RAList _ Nil) = errorEmptyList "head"-head (RAList _ (Cons _ (Leaf x) _)) = x-head (RAList _ (Cons _ (Node x _ _) _)) = x+head :: RAList a -> Maybe a+head = fmap fst . uncons -- | Complexity /O(log n)/. last :: RAList a -> a last xs@(RAList s _) = xs !! (s-1) --- | Complexity /O(1)/.-tail :: RAList a -> RAList a-tail (RAList _ Nil) = errorEmptyList "tail"-tail (RAList s (Cons _ (Leaf _) wts)) = RAList (s-1) wts-tail (RAList s (Cons w (Node x l r) wts)) = RAList (s-1) (Cons w2 l (Cons w2 r wts))- where w2 = w `quot` 2+half :: Word64 -> Word64+half n = n `quot` 2 +-- | Complexity /O(log n)/.+(!!) :: RAList a -> Word64 -> a+RAList s wts !! n | n < 0 = error "Data.RAList.!!: negative index"+ | n >= s = error "Data.RAList.!!: index too large"+ | otherwise = ix n wts+ where ix j (Cons w t wts') | j < w = ixt j (w `quot` 2) t+ | otherwise = ix (j-w) wts'+ ix _ _ = error "Data.RAList.!!: impossible"+ ixt 0 0 (Leaf x) = x+ ixt 0 _ (Node x _l _r) = x+ ixt j w (Node _x l r) | j <= w = ixt (j-1) (w `quot` 2) l+ | otherwise = ixt (j-1-w) (w `quot` 2) r+ ixt _j _w _ = error "Data.RAList.!!: impossible"++lookup :: forall a. Word64 -> Top a -> a+lookup i xs = runIdentity (lookupM i xs)++lookupM :: forall (m :: * -> *) a. Monad m => Word64 -> Top a -> m a+lookupM jx zs = look zs jx+ where look Nil _ = fail "RandList.lookup bad subscript"+ look (Cons j t xs) i+ | i < j = lookTree j t i+ | otherwise = look xs (i - j)++ lookTree _ (Leaf x) i+ | i == 0 = return x+ | otherwise = nothing+ lookTree j (Node x s t) i+ | i > k = lookTree k t (i - 1 - k)+ | i /= 0 = lookTree k s (i - 1)+ | otherwise = return x+ where k = half j+ nothing = fail "RandList.lookup: not found"+ --- this wont fly long term++lookupWithDefault :: forall t. t -> Word64 -> Top t -> t+lookupWithDefault d jx zs = look zs jx+ where look Nil _ = d+ look (Cons j t xs) i+ | i < j = lookTree j t i+ | otherwise = look xs (i - j)++ lookTree _ (Leaf x) i+ | i == 0 = x+ | otherwise = d+ lookTree j (Node x s t) i+ | i > k = lookTree k t (i - 1 - k)+ | i /= 0 = lookTree k s (i - 1)+ | otherwise = x+ where k = half j++-- | Complexity /O(1)/.+tail :: RAList a -> Maybe (RAList a)+tail = fmap snd . uncons -- XXX Is there some clever way to do this? init :: RAList a -> RAList a init = fromList . Prelude.init . toList@@ -314,12 +398,14 @@ null (RAList s _) = s == 0 -- | Complexity /O(1)/.-length :: RAList a -> Int+length :: RAList a -> Word64 length (RAList s _) = s map :: (a->b) -> RAList a -> RAList b map = fmap ++ reverse :: RAList a -> RAList a reverse = fromList . Prelude.reverse . toList @@ -378,63 +464,89 @@ minimum xs | null xs = errorEmptyList "minimum" | otherwise = foldl1 min xs -replicate :: Int -> a -> RAList a-replicate n = fromList . Prelude.replicate n+replicate :: Word64 -> a -> RAList a+replicate n v = fromList $ Prelude.replicate (fromIntegral n) v -take :: Int -> RAList a -> RAList a-take n = fromList . Prelude.take n . toList+take :: Word64 -> RAList a -> RAList a+take n ls | n < fromIntegral (maxBound :: Int) = fromList $ Prelude.take (fromIntegral n) $ toList ls+ | otherwise = ls --- | Complexity /O(log n)/.-drop :: Int -> RAList a -> RAList a+-- | drop i l+-- @`drop` i l@ where l has length n has worst case complexity Complexity /O(log n)/, Average case+-- complexity should be /O(min(log i, log n))/.+drop :: Word64 -> RAList a -> RAList a drop n xs | n <= 0 = xs-drop n xs@(RAList s _) | n >= s = empty+drop n _xs@(RAList s _) | n >= s = empty drop n (RAList s wts) = RAList (s-n) (loop n wts) where loop 0 xs = xs- loop n (Cons w _ xs) | w <= n = loop (n-w) xs- loop n (Cons w (Node _ l r) xs) = loop (n-1) (Cons w2 l (Cons w2 r xs)) where w2 = w `quot` 2+ loop m (Cons w _ xs) | w <= m = loop (m-w) xs -- drops full trees+ loop m (Cons w tre xs) = splitTree m w tre xs -- splits tree loop _ _ = error "Data.RAList.drop: impossible" -splitAt :: Int -> RAList a -> (RAList a, RAList a)+-- helper function for drop+-- drops the first n elements of the tree and adds them to the front+splitTree :: Word64 -> Word64 -> Tree a -> Top a -> Top a+splitTree n treeSize tree@(Node _ l r) xs =+ case (compare n 1, n <= halfTreeSize) of+ (GT {- n==0 -}, _ ) -> Cons treeSize tree xs+ (EQ {- n==1 -}, _ ) -> Cons halfTreeSize l (Cons halfTreeSize r xs)+ (_, True ) -> splitTree (n-1) halfTreeSize l (Cons halfTreeSize r xs)+ (_, False) -> splitTree (n-halfTreeSize-1) halfTreeSize r xs+ where halfTreeSize = treeSize `quot` 2+splitTree n treeSize nd@(Leaf _) xs =+ case compare n 1 of+ EQ {-1-} -> xs+ LT {-0-}-> Cons treeSize nd xs+ GT {- > 1-} -> error "drop invariant violated, must be smaller than current tree"+++++-- Old version of drop+-- worst case complexity /O(n)/+simpleDrop :: Word64 -> RAList a -> RAList a+simpleDrop n xs | n <= 0 = xs+simpleDrop n _xs@(RAList s _) | n >= s = empty+simpleDrop n (RAList s wts) = RAList (s-n) (loop n wts)+ where loop 0 xs = xs+ loop n1 (Cons w _ xs) | w <= n1 = loop (n1-w) xs+ loop n2 (Cons w (Node _ l r) xs) = loop (n2-1) (Cons w2 l (Cons w2 r xs))+ where w2 = w `quot` 2+ loop _ _ = error "Data.RAList.drop: impossible"+++splitAt :: Word64 -> RAList a -> (RAList a, RAList a) splitAt n xs = (take n xs, drop n xs) elem :: (Eq a) => a -> RAList a -> Bool elem x = any (== x) notElem :: (Eq a) => a -> RAList a -> Bool-notElem x = any (/= x)+notElem x = not . elem x -- aka all (/=) -lookup :: (Eq a) => a -> RAList (a, b) -> Maybe b-lookup x xys = Prelude.lookup x (toList xys)+-- naive list based lookup+lookupL :: (Eq a) => a -> RAList (a, b) -> Maybe b+lookupL x xys = Prelude.lookup x (toList xys) filter :: (a->Bool) -> RAList a -> RAList a filter p xs =- if null xs then- empty- else- let x = head xs- ys = filter p (tail xs)- in if p x then x `cons` ys else ys+ case uncons xs of+ Nothing -> empty+ Just(h,tl) ->+ let+ ys = filter p tl+ in+ if p h then h `cons` ys else ys + partition :: (a->Bool) -> RAList a -> (RAList a, RAList a) partition p xs = (filter p xs, filter (not . p) xs) --- | Complexity /O(log n)/.-(!!) :: RAList a -> Int -> a-RAList s wts !! n | n < 0 = error "Data.RAList.!!: negative index"- | n >= s = error "Data.RAList.!!: index too large"- | otherwise = ix n wts- where ix n (Cons w t wts') | n < w = ixt n (w `quot` 2) t- | otherwise = ix (n-w) wts'- ix _ _ = error "Data.RAList.!!: impossible"- ixt 0 0 (Leaf x) = x- ixt 0 _ (Node x l r) = x- ixt n w (Node x l r) | n <= w = ixt (n-1) (w `quot` 2) l- | otherwise = ixt (n-1-w) (w `quot` 2) r- ixt n w _ = error "Data.RAList.!!: impossible" + zip :: RAList a -> RAList b -> RAList (a, b)-zip = zipWith (,) +zip = zipWith (,) zipWith :: (a->b->c) -> RAList a -> RAList b -> RAList c zipWith f xs1@(RAList s1 wts1) xs2@(RAList s2 wts2)@@ -444,7 +556,7 @@ zipTree (Node x1 l1 r1) (Node x2 l2 r2) = Node (f x1 x2) (zipTree l1 l2) (zipTree r1 r2) zipTree _ _ = error "Data.RAList.zipWith: impossible" zipTop Nil Nil = Nil- zipTop (Cons w t1 xs1) (Cons _ t2 xs2) = Cons w (zipTree t1 t2) (zipTop xs1 xs2)+ zipTop (Cons w t1 xss1) (Cons _ t2 xss2) = Cons w (zipTree t1 t2) (zipTop xss1 xss2) zipTop _ _ = error "Data.RAList.zipWith: impossible" unzip :: RAList (a, b) -> (RAList a, RAList b)@@ -452,22 +564,22 @@ -- | Change element at the given index. -- Complexity /O(log n)/.-update :: Int -> a -> RAList a -> RAList a+update :: Word64 -> a -> RAList a -> RAList a update i x = adjust (const x) i -- | Apply a function to the value at the given index. -- Complexity /O(log n)/.-adjust :: (a->a) -> Int -> RAList a -> RAList a+adjust :: (a->a) -> Word64 -> RAList a -> RAList a adjust f n (RAList s wts) | n < 0 = error "Data.RAList.adjust: negative index" | n >= s = error "Data.RAList.adjust: index too large" | otherwise = RAList s (adj n wts)- where adj n (Cons w t wts') | n < w = Cons w (adjt n (w `quot` 2) t) wts'- | otherwise = Cons w t (adj (n-w) wts')- adj _ _ = error "Data.RAList.adjust: impossible"+ where adj j (Cons w t wts') | j < w = Cons w (adjt j (w `quot` 2) t) wts'+ | otherwise = Cons w t (adj (j-w) wts')+ adj j _ = error ("Data.RAList.adjust: impossible Nil element: " <> show j) adjt 0 0 (Leaf x) = Leaf (f x) adjt 0 _ (Node x l r) = Node (f x) l r- adjt n w (Node x l r) | n <= w = Node x (adjt (n-1) (w `quot` 2) l) r- | otherwise = Node x l (adjt (n-1-w) (w `quot` 2) r)+ adjt j w (Node x l r) | j <= w = Node x (adjt (j-1) (w `quot` 2) l) r+ | otherwise = Node x l (adjt (j-1-w) (w `quot` 2) r) adjt _ _ _ = error "Data.RAList.adjust: impossible" -- XXX Make this a good producer
+ benchmark/benchmarking.hs view
@@ -0,0 +1,63 @@++module Main where+import Criterion.Main+import Data.RAList++hundred :: RAList Int+hundred = fromList [0..100]++thousand :: RAList Int+thousand = fromList [0..1000]++tenThousand :: RAList Int+tenThousand = fromList [0..10000]++hundredThousand :: RAList Int+hundredThousand = fromList [0..100000]++million :: RAList Int+million = fromList [0..1000000]++tenMillion :: RAList Int+tenMillion = fromList [0..10000000]++main = defaultMain [+ bgroup "drop"+ [ bench "TenThousand" $ whnf (Data.RAList.drop 100) tenThousand,+ bench "HundredThousand" $ whnf (Data.RAList.drop 100) hundredThousand,+ bench "Million" $ whnf (Data.RAList.drop 100) million,+ bench "TenMillion" $ whnf (Data.RAList.drop 100) tenMillion,++ bench "TenThousand-Drop1" $ whnf (Data.RAList.drop 1) tenThousand,+ bench "HundredThousand-Drop1" $ whnf (Data.RAList.drop 1) hundredThousand,+ bench "Million-Drop1" $ whnf (Data.RAList.drop 1) million,+ bench "TenMillion-Drop1" $ whnf (Data.RAList.drop 1) tenMillion+ ],++ bgroup "simpleDrop"+ [ bench "TenThousand" $ whnf (Data.RAList.simpleDrop 100) tenThousand,+ bench "HundredThousand" $ whnf (Data.RAList.simpleDrop 100) hundredThousand,+ bench "Million" $ whnf (Data.RAList.simpleDrop 100) million,+ bench "TenMillion" $ whnf (Data.RAList.simpleDrop 100) tenMillion,++ bench "TenThousand-Drop1" $ whnf (Data.RAList.simpleDrop 1) tenThousand,+ bench "HundredThousand-Drop1" $ whnf (Data.RAList.simpleDrop 1) hundredThousand,+ bench "Million-Drop1" $ whnf (Data.RAList.simpleDrop 1) million,+ bench "TenMillion-Drop1" $ whnf (Data.RAList.simpleDrop 1) tenMillion+ ],++ bgroup "cons"+ [ bench "hundred" $ whnf (Data.RAList.cons 0) hundred,+ bench "thousand" $ whnf (Data.RAList.cons 0) thousand+ ],++ bgroup "uncons"+ [ bench "hundred" $ whnf Data.RAList.uncons hundred,+ bench "thousand" $ whnf Data.RAList.uncons thousand+ ],+ bgroup "lookup last element"+ [ bench "TenThousand" $ whnf (tenThousand Data.RAList.!!) 10000,+ bench "HundredThousand" $ whnf (hundredThousand Data.RAList.!!) 100000,+ bench "Million" $ whnf (million Data.RAList.!!) 1000000,+ bench "TenMillion" $ whnf (tenMillion Data.RAList.!!) 10000000+ ] ]
ralist.cabal view
@@ -1,9 +1,9 @@ Name: ralist-Cabal-Version: >= 1.2-Version: 0.1.0.0+Cabal-Version: >= 1.20+Version: 0.2.0.0 License: BSD3-Author: Lennart Augustsson-Maintainer: Lennart Augustsson+Author: Lennart Augustsson, Carter Schonwald+Maintainer: Carter Schonwald Category: Data Structures Synopsis: Random access list with a list compatible interface. Stability: experimental@@ -12,7 +12,57 @@ Random access list have same complexity as lists with some exceptions, the notable one being that (!!) is O(log n) instead of O(n). RALists have to be finite.+-- URL for the project homepage or repository.+homepage: http://github.com/cartazio/ralist +source-repository head+ type: git+ location: https://github.com/cartazio/ralist.git+++-- You can disable the hunit test suite with -f-test-hunit+flag test-hspec+ default: True+ manual: True+ Library Build-Depends: base >= 3 && < 6 Exposed-modules: Data.RAList+ ghc-options: -Wall -O2+ default-language: Haskell2010+ -- Build-depends: semigroups == 0.18.*+ if impl(ghc >= 8.0)+ ghc-options: -Wcompat -Wnoncanonical-monad-instances -Wnoncanonical-monadfail-instances+ else+ -- provide/emulate `Control.Monad.Fail` and `Data.Semigroups` API for pre-GHC8+ build-depends: fail == 4.9.*, semigroups == 0.18.*++test-suite hspec+ type: exitcode-stdio-1.0++ main-is: hspec.hs+ default-language: Haskell2010+ ghc-options: -w -threaded -rtsopts -with-rtsopts=-N+ hs-source-dirs: tests++ if !flag(test-hspec)+ buildable: False+ else+ build-depends:+ base,+ ralist,+ hspec >= 2.2 && < 2.3+++benchmark benchmarking+ type: exitcode-stdio-1.0+ main-is: benchmarking.hs+ default-language: Haskell2010+ hs-source-dirs: benchmark+ ghc-options: -O2++ build-depends:+ base,+ ralist,+ criterion,+ deepseq
+ tests/hspec.hs view
@@ -0,0 +1,708 @@+module Main where++import Data.RAList+import Test.Hspec+import Control.Exception (evaluate)+++main = hspec $ do+ describe "RAList.cons" $ do+ it "adds to an empty list" $ do+ cons 1 empty `shouldBe` (fromList [1] :: RAList Int)+ it "adds to a list of length 1" $ do+ cons 1 (fromList [2]) `shouldBe` (fromList [1,2] :: RAList Int)+ it "add to a list of length 10" $ do+ cons 1 (fromList [2..11]) `shouldBe`+ (fromList [1..11] :: RAList Int)+++ describe "RAList.uncons" $ do+ it "deletes the first element of a list of length 1" $ do+ uncons (fromList ['a']) `shouldBe`+ (Just ('a',(fromList [])) :: Maybe (Char, RAList Char))+ it "deletes the first element of a list of length 3" $ do+ uncons (fromList ['a'..'c']) `shouldBe`+ (Just ('a',(fromList ['b','c'])) :: Maybe (Char, RAList Char))+ it "returns Nothing when it uncons from an empty list" $ do+ (uncons empty :: Maybe (Char, RAList Char)) `shouldBe`+ (Nothing :: Maybe (Char, RAList Char))++ describe "RAList.head" $ do -- This is a Maybe+ it "gets the first element of a list of length 1" $ do+ (Data.RAList.head (fromList [1 :: Int ]) ) `shouldBe` Just 1+ it "gets the first element of a list of length 3" $ do+ (Data.RAList.head (fromList [1 .. 3 :: Int ])) `shouldBe` Just 1+ it "gets the first element of a list of length 9" $ do+ (Data.RAList.head (fromList [1 .. 9 :: Int])) `shouldBe` Just 1+ it "gets nothing if the list is empty" $ do+ Data.RAList.head (fromList ([] :: [Int])) `shouldBe` Nothing++ describe "RAList.last" $ do -- This is not a Maybe+ it "gets the last element of a list of length 1" $ do+ (Data.RAList.last (fromList [1]) ) `shouldBe`+ (1 :: Integer)+ it "gets the last element of a list of length 3" $ do+ Data.RAList.last (fromList [1..3]) `shouldBe`+ (3 :: Integer)+ it "gets the last element of a list of length 9" $ do+ Data.RAList.last (fromList [1..9]) `shouldBe`+ (9 :: Integer)+ it "gets nothing if the list is empty" $ do+ evaluate (Data.RAList.last empty) `shouldThrow` anyException++ describe "RAList.tail" $ do -- This is a Maybe+ it "gets everything after the first element of a list of length 1" $ do+ (Data.RAList.tail (fromList [1]) ) `shouldBe`+ (Just (fromList []) :: Maybe (RAList Integer))+ it "gets everything after the first element of a list of length 3" $ do+ (Data.RAList.tail (fromList [1..3])) `shouldBe`+ (Just (fromList [2,3]) :: Maybe (RAList Integer))+ it "gets everything after the first element of a list of length 9" $ do+ (Data.RAList.tail (fromList [1..9])) `shouldBe`+ (Just (fromList [2..9]) :: Maybe (RAList Integer))+ it "gets nothing if the list is empty" $ do+ Data.RAList.tail empty `shouldBe` (Nothing :: Maybe (RAList Integer))++ describe "RAList.init" $ do -- This is not a Maybe+ it "gets everything before the last element of a list of length 1" $ do+ (Data.RAList.init (fromList [1]) ) `shouldBe` (fromList [] :: RAList Integer)+ it "gets everything but the last element of a list of length 3" $ do+ Data.RAList.init (fromList [1..3]) `shouldBe` (fromList [1,2] :: RAList Integer)+ it "gets everything but the last element of a list of length 9" $ do+ Data.RAList.init (fromList [1..9]) `shouldBe` (fromList [1..8] :: RAList Integer)++ it "gets nothing if the list is empty" $ do+ evaluate (Data.RAList.init empty) `shouldThrow` anyException++ describe "RAList.null" $ do+ it "returns True if it is given an empty list" $ do+ Data.RAList.null empty `shouldBe` (True :: Bool)+ it "return False if it is given a non-empty list" $ do+ Data.RAList.null (fromList [1]) `shouldBe` (False :: Bool)++ describe "RAList.length" $ do+ it "returns 0 if the list is empty" $ do+ Data.RAList.length empty `shouldBe` 0+ it "returns 1 if the list has length 1" $ do+ Data.RAList.length (fromList [1]) `shouldBe` 1+ it "returns 3 if the list has lenght 3"$ do+ Data.RAList.length (fromList [1..3]) `shouldBe` 3+ it "returns 9 if the list has length 9" $ do+ Data.RAList.length (fromList [1..9]) `shouldBe` 9++ describe "RAList.lookupL" $ do+ describe "for a list of length 1" $ do+ let ra = fromList [('a','b')]+ it "returns the first value correctly" $ do+ lookupL 'a' ra `shouldBe` (Just 'b' :: Maybe Char)+ it "returns Nothing for a nonexistent key value" $ do+ lookupL 'z' ra `shouldBe` (Nothing :: Maybe Char)+ describe "for a list of length 3" $ do+ let ra = fromList [('a','b'),('c','d'),('e','f')]+ it "returns the first value correctly" $ do+ lookupL 'a' ra `shouldBe` (Just 'b':: Maybe Char)+ it "returns the last value correctly" $ do+ lookupL 'e' ra `shouldBe` (Just 'f':: Maybe Char)+ it "returns the middle value correctly" $ do+ lookupL 'c' ra `shouldBe` (Just 'd':: Maybe Char)+ it "returns Nothing for a nonexistent key value" $ do+ lookupL 'z' ra `shouldBe` (Nothing :: Maybe Char)+ describe "for a list of length 9" $ do+ let ra = fromList [('a','b'),('c','d'),('e','f'),('g','h'),('i','j'),('k','l'),('m','n'),('o','p'),('q','r')]+ it "returns the first value correctly" $ do+ lookupL 'a' ra `shouldBe` (Just 'b':: Maybe Char)+ it "returns the second value correctly" $ do+ lookupL 'c' ra `shouldBe` (Just 'd':: Maybe Char)+ it "returns the third value correctly" $ do+ lookupL 'e' ra `shouldBe` (Just 'f':: Maybe Char)+ it "returns the fourth value correctly" $ do+ lookupL 'g' ra `shouldBe` (Just 'h':: Maybe Char)+ it "returns the last value correctly" $ do+ lookupL 'q' ra `shouldBe` (Just 'r':: Maybe Char)+ it "returns Nothing for a nonexistent key value" $ do+ lookupL 'z' ra `shouldBe` (Nothing :: Maybe Char)+ describe "for an empty list" $ do+ it "return Nothing when called with an empty list" $ do+ lookupL 'a' empty `shouldBe` (Nothing :: Maybe Char)++ describe "RAList.map" $ do+ describe "for a list of length 1" $ do+ it "maps from Int to Int"$ do+ Data.RAList.map (\x -> 2*x) (fromList [1]) `shouldBe`+ (fromList [2] :: RAList Int)+ it "maps from Int to String" $ do+ Data.RAList.map (\x -> 'a') (fromList [1]) `shouldBe`+ (fromList ['a'] :: RAList Char)+ it "maps from Char to Int" $ do+ Data.RAList.map (\x -> 1) (fromList ['a']) `shouldBe`+ (fromList [1] :: RAList Int)+ it "maps from Int to [Int]" $ do+ Data.RAList.map (\x -> [x]) (fromList [1]) `shouldBe`+ (fromList [[1]] :: RAList [Int])+ it "maps from [Int] to Int" $ do+ Data.RAList.map (\x -> x Prelude.!! 0)+ ((fromList [[1]]) :: RAList [Int])+ `shouldBe` (fromList [1] :: RAList Int)+ describe "for a list of length 3" $ do+ it "maps from Int to Int" $ do+ Data.RAList.map (\x -> 2*x) (fromList [1..3]) `shouldBe`+ (fromList [2,4,6] :: RAList Int)+ describe "for a list of length 9" $ do+ it "maps from Int to Int" $ do+ Data.RAList.map (\x -> 2*x) (fromList [1..9])+ `shouldBe`+ ((fromList [2,4..18]) :: RAList Int)+ describe "for an empty list" $ do+ it "returns an empty list of correct type" $ do+ Data.RAList.map (\x -> 'a') empty `shouldBe`+ (empty :: RAList Char)++ describe "RAList.reverse" $ do+ it "does nothing to a list of length 1" $ do+ Data.RAList.reverse (fromList [1]) `shouldBe`+ (fromList [1] :: RAList Int)+ it "reverses a list of length 3" $ do+ Data.RAList.reverse (fromList [1..3]) `shouldBe`+ (fromList [3,2,1] :: RAList Int)+ it "reverse a list of length 9" $ do+ Data.RAList.reverse (fromList [1..9]) `shouldBe`+ (fromList [9,8..1] :: RAList Int)+ it "does nothing to an empty list" $ do+ Data.RAList.reverse (empty :: RAList Int) `shouldBe`+ (empty :: RAList Int)++ -- Only tests for one list length because it immediately turns the RALists+ -- into standard lists with 'toList', which is tested elsewhere+ describe "folds" $ do+ let rai = fromList [1..3]+ let ras = fromList ["a","b","c"]+ describe "RAList.foldl" $ do+ it "adds Ints in a list" $ do+ Data.RAList.foldl (+) 0 rai `shouldBe` (6 :: Int)+ it "subtracts Ints in a list" $ do+ Data.RAList.foldl (-) 0 rai `shouldBe` ((-6) :: Int)+ it "concatenates Strings in a list" $ do+ Data.RAList.foldl (Prelude.++) "" ras `shouldBe`+ ("abc" :: [Char])+ describe "RAList.foldl1" $ do+ it "adds Ints in a list" $ do+ Data.RAList.foldl1 (+) rai `shouldBe` (6 :: Int)+ it "subtracts Ints in a list" $ do+ Data.RAList.foldl1 (-) rai `shouldBe` ((-4) :: Int)+ it "concatenates Strings in a list" $ do+ Data.RAList.foldl1 (Prelude.++) ras `shouldBe`+ ("abc" :: [Char])+ describe "RAList.foldr" $ do+ it "adds Ints in a list" $ do+ Data.RAList.foldr (+) 0 rai `shouldBe` (6 :: Int)+ it "subtracts Ints in a list" $ do+ Data.RAList.foldr (-) 0 rai `shouldBe` (2 :: Int)+ it "concatenates Strings in a list" $ do+ Data.RAList.foldr (Prelude.++) "" ras `shouldBe`+ ("abc" :: [Char])+ describe "RAList.foldr1" $ do+ it "adds Ints in a list" $ do+ Data.RAList.foldr1 (+) rai `shouldBe` (6 :: Int)+ it "subtracts Ints in a list" $ do+ Data.RAList.foldr1 (-) rai `shouldBe` (2 :: Int)+ it "concatenates characters in a list" $ do+ Data.RAList.foldr1 (Prelude.++) ras `shouldBe`+ ("abc" :: [Char])++ describe "RAList.concat" $ do+ it "concatenates list of empty lists" $ do+ Data.RAList.concat (fromList [empty, empty]) `shouldBe`+ (empty :: RAList Integer)+ it "concatenates an empty list" $ do+ Data.RAList.concat empty `shouldBe` (empty :: RAList Integer)+ it "concatenates lists of the same length" $ do+ Data.RAList.concat+ (fromList [fromList [1,2], fromList [1,2], fromList [1,2]])+ `shouldBe` (fromList [1,2,1,2,1,2] :: RAList Int)+ it "concatenates lists of different lengths" $ do+ Data.RAList.concat+ (fromList [fromList [], fromList [1], fromList [1,2],+ fromList [1..3], fromList [1..9]])+ `shouldBe`+ (fromList [1,1,2,1,2,3,1,2,3,4,5,6,7,8,9] :: RAList Int)++ describe "RAList.concatMap" $ do+ describe "for lists of length 1" $ do+ it "maps (x -> [x]) on a list of integers" $ do+ Data.RAList.concatMap (\x -> fromList [x])+ (fromList [1]) `shouldBe`+ (fromList [1] :: RAList Int)+ it "maps (x -> [1, length x]) on a list of Strings" $ do+ Data.RAList.concatMap+ (\x -> fromList [1, (Prelude.length x)])+ (fromList ["abc"]) `shouldBe`+ (fromList [1,3] :: RAList Int)+ it "returns an empty list when it maps to an empty list" $ do+ Data.RAList.concatMap+ (\x -> empty) (fromList [1]) `shouldBe`+ (fromList [] :: RAList Int)+ describe "for lists of length 3" $ do+ it "maps (x -> [x]) on a list of integers" $ do+ Data.RAList.concatMap (\x -> fromList [x])+ (fromList [1..3]) `shouldBe`+ (fromList [1..3] :: RAList Int)+ it "maps (x -> [1, length x]) on a list of Strings" $ do+ Data.RAList.concatMap+ (\x -> fromList [1, (Prelude.length x)])+ (fromList ["a","ab", "abc"]) `shouldBe`+ (fromList [1,1,1,2,1,3] :: RAList Int)+ it "returns an empty list when it maps to an empty list" $ do+ Data.RAList.concatMap+ (\x -> empty) (fromList [1..3]) `shouldBe`+ (fromList [] :: RAList Int)+ describe "for lists of length " $ do+ it "maps (x -> [x]) on a list of integers" $ do+ Data.RAList.concatMap (\x -> fromList [x])+ (fromList [1..9]) `shouldBe`+ (fromList [1..9] :: RAList Int)+ it "maps (x -> [1, length x]) on a list of Strings" $ do+ Data.RAList.concatMap+ (\x -> fromList [1, (Prelude.length x)])+ (fromList ["a","ab", "abc","a","a","a","a","a","abcd"])+ `shouldBe`+ (fromList [1,1,1,2,1,3,1,1,1,1,1,1,1,1,1,1,1,4]+ :: RAList Int)+ it "returns an empty list when it maps to an empty list" $ do+ Data.RAList.concatMap+ (\x -> empty) (fromList [1..9]) `shouldBe`+ (fromList [] :: RAList Int)++ describe "logic functions" $ do+ describe "Data.RAList.and" $ do+ it "returns False when first value is False" $ do+ Data.RAList.and+ (fromList [False, True, True, True, True, True, True, True,+ True])+ `shouldBe` (False :: Bool)+ it "returns False when last value is True" $ do+ Data.RAList.and+ (fromList [True, True, True, True, True, True, True,+ True, False])+ `shouldBe` (False :: Bool)+ it "returns False when the only value is False" $ do+ Data.RAList.and+ (fromList [False, False, False, False, False, False, False,+ False, False])+ `shouldBe` (False :: Bool)+ it "returns False with a list of length one containing False" $ do+ Data.RAList.and (fromList [False]) `shouldBe` (False :: Bool)+ it " returns True with a list of length one containing True" $ do+ Data.RAList.and (fromList [True]) `shouldBe` (True :: Bool)+ it "returns True when the only value is True" $ do+ Data.RAList.and+ (fromList [True, True, True, True, True, True, True, True,+ True])+ `shouldBe` (True :: Bool)+ it "returns True for an empty list" $ do+ Data.RAList.and empty `shouldBe` (True :: Bool)+ describe "Ralist.or" $ do+ it "returns True when first value is True" $ do+ Data.RAList.or+ (fromList [True, False, False, False, False, False, False,+ False, False])+ `shouldBe` (True :: Bool)+ it "returns True when last value is True" $ do+ Data.RAList.or+ (fromList [False, False, False, False, False, False, False,+ False, True])+ `shouldBe` (True :: Bool)+ it "returns False when the only value is False" $ do+ Data.RAList.or+ (fromList [False, False, False, False, False, False, False,+ False, False])+ `shouldBe` (False :: Bool)+ it "returns False with a list of length one containing False" $ do+ Data.RAList.or (fromList [False]) `shouldBe` (False :: Bool)+ it " returns True with a list of length one containing True" $ do+ Data.RAList.or (fromList [True]) `shouldBe` (True :: Bool)+ it "returns True when the only value is True" $ do+ Data.RAList.or+ (Data.RAList.replicate 9 True)+ `shouldBe` (True :: Bool)+ it "returns False for an empty list" $ do+ Data.RAList.or empty `shouldBe` (False :: Bool)+ describe "RAList.any" $ do+ it "returns True when first value evaluates to True" $ do+ Data.RAList.any (\x -> x)+ (fromList [True, False, False, False, False, False, False,+ False, False])+ `shouldBe` (True :: Bool)+ it "returns True when last value is True" $ do+ Data.RAList.any (\x -> x)+ (fromList [False, False, False, False, False, False, False,+ False, True])+ `shouldBe` (True :: Bool)+ it "returns False when the only value is False" $ do+ Data.RAList.any (\x -> x)+ (Data.RAList.replicate 9 False)+ `shouldBe` (False :: Bool)+ it "returns False with a list of length one containing False" $ do+ Data.RAList.any (\x -> x) (fromList [False]) `shouldBe`+ (False :: Bool)+ it " returns True with a list of length one containing True" $ do+ Data.RAList.any (\x -> x) (fromList [True]) `shouldBe` (True :: Bool)+ it "returns True when the only value is True" $ do+ Data.RAList.any (\x -> x)+ (Data.RAList.replicate 9 True)+ `shouldBe` (True :: Bool)+ it "returns False for an empty list" $ do+ Data.RAList.any (\x -> x) empty `shouldBe` (False :: Bool)+ describe "RAList.all" $ do+ it "returns False when first value evaluates to False" $ do+ Data.RAList.all (\x -> x)+ (fromList [False, True, True, True, True, True, True, True,+ True])+ `shouldBe` (False :: Bool)+ it "returns False when last value evaluates to False" $ do+ Data.RAList.all (\x -> x)+ (fromList [True, True, True, True, True, True, True,+ True, False])+ `shouldBe` (False :: Bool)+ it "returns False when the only value evaluates to False" $ do+ Data.RAList.all (\x -> x)+ (Data.RAList.replicate 9 False)+ `shouldBe` (False :: Bool)+ it "returns False with a list of one value which evaluates to False"+ $ do+ Data.RAList.all (\x -> x) (fromList [False]) `shouldBe` (False :: Bool)+ it " returns True with a list of one value which evaluates to True"+ $ do+ Data.RAList.all (\x -> x) (fromList [True]) `shouldBe` (True :: Bool)+ it "returns True when the only value evaluates to True" $ do+ Data.RAList.all (\x -> x)+ (Data.RAList.replicate 9 True)+ `shouldBe` (True :: Bool)+ it "returns True for an empty list" $ do+ Data.RAList.all (\x -> x) empty `shouldBe` (True :: Bool)++ describe "Math operations" $ do+ describe "RAList.sum" $ do+ it "adds all ints in a list of length 1" $ do+ Data.RAList.sum (fromList [3]) `shouldBe` (3 :: Int)+ it "adds all ints in a list of length 3" $ do+ Data.RAList.sum (fromList [1,1,1]) `shouldBe` (3 :: Int)+ it "adds all ints in a list of length 9" $ do+ Data.RAList.sum (Data.RAList.replicate 9 1) `shouldBe` (9 :: Int)+ it "returns 0 when given an empty list" $ do+ Data.RAList.sum empty `shouldBe` (0 :: Int)+ describe "RAList.product" $ do+ it "multiplies all ints in a list of length 1" $ do+ Data.RAList.product (fromList [3]) `shouldBe` (3 :: Int)+ it "multiplies all ints in a list of length 3" $ do+ Data.RAList.product (fromList [2,2,2]) `shouldBe` (8 :: Int)+ it "multiplies all ints in a list of length 9" $ do+ Data.RAList.product (Data.RAList.replicate 9 2) `shouldBe`+ (512 :: Int)+ it "returns 1 when given an empty list" $ do+ Data.RAList.product empty `shouldBe` (1 :: Int)++ describe "extrema" $ do+ describe "RAList.maximum" $ do+ describe "for list of length 1" $ do+ it "returns the value" $ do+ Data.RAList.maximum (fromList [1]) `shouldBe` (1 :: Int)+ describe "for a list of length 3" $ do+ it "can return the first value" $ do+ Data.RAList.maximum (fromList [3,1,2]) `shouldBe` (3 :: Int)+ it "can return the last value" $ do+ Data.RAList.maximum (fromList [1..3]) `shouldBe` (3 :: Int)+ describe "for a list of length 9" $ do+ let ra = fromList [1..9]+ it "can return the first value" $ do+ Data.RAList.maximum (update 0 10 ra) `shouldBe` (10 :: Int)+ it "can return the second value" $ do+ Data.RAList.maximum (update 1 10 ra) `shouldBe` (10 :: Int)+ it "can return the third value" $ do+ Data.RAList.maximum (update 2 10 ra) `shouldBe` (10 :: Int)+ it "can return the fourth value" $ do+ Data.RAList.maximum (update 3 10 ra) `shouldBe` (10 :: Int)+ it "can return the last value" $ do+ -- Specifies the list rather than updating the last value+ -- because update is currently broken+ Data.RAList.maximum (fromList [1,2,3,4,5,6,7,8,10]) `shouldBe`+ (10 :: Int)+ describe "for an empty list" $ do+ it "throws an exception" $ do+ evaluate (Data.RAList.maximum (empty :: RAList Int)) `shouldThrow`+ anyException+ describe "RAList.minimum" $ do+ describe "other" $ do+ describe "for list of length 1" $ do+ it "returns the value" $ do+ Data.RAList.minimum (fromList [1]) `shouldBe` (1 :: Int)+ describe "for a list of length 3" $ do+ it "can return the first value" $ do+ Data.RAList.minimum (fromList [1,3,2]) `shouldBe` (1 :: Int)+ it "can return the last value" $ do+ Data.RAList.minimum (fromList [3,2,1]) `shouldBe` (1 :: Int)++ describe "for a list of length 9" $ do+ let ra = fromList [1..9]+ it "can return the first value" $ do+ Data.RAList.minimum (update 0 0 ra) `shouldBe` (0 :: Int)+ it "can return the second value" $ do+ Data.RAList.minimum (update 1 0 ra) `shouldBe` (0 :: Int)+ it "can return the third value" $ do+ Data.RAList.minimum (update 2 0 ra) `shouldBe` (0 :: Int)+ it "can return the fourth value" $ do+ Data.RAList.minimum (update 3 0 ra) `shouldBe` (0 :: Int)+ it "can return the last value" $ do+ Data.RAList.minimum (fromList [1,2,3,4,5,6,7,8,0]) `shouldBe`+ (0 :: Int)+ describe "for an empty list" $ do+ it "throws an exception" $ do+ evaluate (Data.RAList.minimum (empty :: RAList Int)) `shouldThrow`+ anyException++ describe "RAList.replicate" $ do+ it "creates an empty list" $ do+ Data.RAList.replicate 0 1 `shouldBe` (empty :: RAList Int)+ it "creates a list of length 1" $ do+ Data.RAList.replicate 1 1 `shouldBe` (fromList [1] :: RAList Int)+ it "creates a list of length 3" $ do+ Data.RAList.replicate 3 1 `shouldBe` (fromList [1,1,1] :: RAList Int)+ it "creates a list of length 9" $ do+ Data.RAList.replicate 9 1 `shouldBe`+ (fromList [1,1,1,1,1,1,1,1,1] :: RAList Int)++ describe "RAList.take" $ do+ let ra = fromList [1..9]+ it "takes the first Data.RAList.element of a list" $ do+ Data.RAList.take 1 ra `shouldBe` (fromList [1] :: RAList Int)+ it "takes the first 2 Data.RAList.elements of a list" $ do+ Data.RAList.take 2 ra `shouldBe` (fromList [1,2] :: RAList Int)+ it "takes the first 3 Data.RAList.elements of a list" $ do+ Data.RAList.take 3 ra `shouldBe` (fromList [1..3] :: RAList Int)+ it "takes the first 4 Data.RAList.elements of a list" $ do+ Data.RAList.take 4 ra `shouldBe` (fromList [1..4] :: RAList Int)+ it "takes all the Data.RAList.elements of a list" $ do+ Data.RAList.take 9 ra `shouldBe` (ra :: RAList Int)+ it "gives an empty list when you Data.RAList.take from an empty list" $ do+ Data.RAList.take 1 empty `shouldBe` (empty :: RAList Int)++ describe "RAList.drop" $ do+ let ra = fromList [1..9]+ it "drops the first Data.RAList.element of a list" $ do+ Data.RAList.drop 1 ra `shouldBe`+ (fromList [2..9] :: RAList Int)+ it "drops the first 2 Data.RAList.elements of a list" $ do+ Data.RAList.drop 2 ra `shouldBe`+ (fromList [3..9] :: RAList Int)+ it "drops the first 3 Data.RAList.elements of a list" $ do+ Data.RAList.drop 3 ra `shouldBe` (fromList [4..9] :: RAList Int)+ it "drops the first 4 Data.RAList.elements of a list" $ do+ Data.RAList.drop 4 ra `shouldBe` (fromList [5..9] :: RAList Int)+ it "drops all the Data.RAList.elements of a list" $ do+ Data.RAList.drop 9 ra `shouldBe` (empty :: RAList Int)+ it "gives an empty list when you drop from an empty list" $ do+ Data.RAList.drop 1 empty `shouldBe` (empty :: RAList Int)++ describe "RAList.splitAt" $ do+ let ra = fromList [1..9]+ it "splitAts the first Data.RAList.element of a list" $ do+ Data.RAList.splitAt 1 ra `shouldBe`+ ((fromList [1], fromList [2..9]) ::+ (RAList Int, RAList Int) )+ it "splitAts the second Data.RAList.element of a list" $ do+ Data.RAList.splitAt 2 ra `shouldBe`+ ((fromList [1,2], fromList [3..9]) ::+ (RAList Int, RAList Int) )+ it "splitAts the third Data.RAList.element of a list" $ do+ Data.RAList.splitAt 3 ra `shouldBe`+ ((fromList [1..3], fromList [4..9]) ::+ (RAList Int, RAList Int) )+ it "splitAts the fourth Data.RAList.element of a list" $ do+ Data.RAList.splitAt 4 ra `shouldBe`+ ((fromList [1..4], fromList [5..9]) ::+ (RAList Int, RAList Int) )+ it "splitAts the last Data.RAList.element of a list" $ do+ Data.RAList.splitAt 9 ra `shouldBe`+ ((ra, empty) :: (RAList Int, RAList Int) )+ it "gives an empty list when you splitAt from an empty list" $ do+ Data.RAList.splitAt 1 empty `shouldBe`+ ((empty, empty) :: (RAList Int, RAList Int) )++ describe "RAList.elem" $ do+ let ra = fromList [1..9]+ it "can find the first Data.RAList.element of a list" $ do+ Data.RAList.elem 1 ra `shouldBe` (True :: Bool)+ it "can find the second Data.RAList.element of a list" $ do+ Data.RAList.elem 2 ra `shouldBe` (True :: Bool)+ it "can find the third Data.RAList.element of a list" $ do+ Data.RAList.elem 3 ra `shouldBe` (True :: Bool)+ it "can find the fourth Data.RAList.element of a list" $ do+ Data.RAList.elem 4 ra `shouldBe` (True :: Bool)+ it "can find the last Data.RAList.element of a list" $ do+ Data.RAList.elem 5 ra `shouldBe` (True :: Bool)+ it "returns false if the Data.RAList.element is not present" $ do+ Data.RAList.elem 10 ra `shouldBe` (False :: Bool)+ it "returns false when given an empty list" $ do+ Data.RAList.elem 1 empty `shouldBe` (False :: Bool)++ describe "RAList.notElem" $ do+ let ra = fromList [1..9]+ it "can find the first Data.RAList.notElement of a list" $ do+ Data.RAList.notElem 1 ra `shouldBe` (False :: Bool)+ it "can find the second Data.RAList.notElement of a list" $ do+ Data.RAList.notElem 2 ra `shouldBe` (False :: Bool)+ it "can find the third Data.RAList.notElement of a list" $ do+ Data.RAList.notElem 3 ra `shouldBe` (False :: Bool)+ it "can find the fourth Data.RAList.notElement of a list" $ do+ Data.RAList.notElem 4 ra `shouldBe` (False :: Bool)+ it "can find the last Data.RAList.notElement of a list" $ do+ Data.RAList.notElem 5 ra `shouldBe` (False :: Bool)+ it "returns false if the Data.RAList.notElement is not present" $ do+ Data.RAList.notElem 10 ra `shouldBe` (True :: Bool)+ it "returns true when give an empty list" $ do+ Data.RAList.notElem 1 empty `shouldBe` (True :: Bool)++ describe "RAList.filter" $ do+ let ra = fromList [1..9]+ it "filters for the first element in a list" $ do+ Data.RAList.filter (\x -> x == 1) ra `shouldBe`+ (fromList [1] :: RAList Int)+ it "filters out the first element in a list" $ do+ Data.RAList.filter (\x -> x > 1) ra `shouldBe`+ (fromList [2..9] :: RAList Int)+ it "filters for the last element in a list" $ do+ Data.RAList.filter (\x -> x == 9) ra `shouldBe`+ (fromList [9] :: RAList Int)+ it "filters out the last element in a list" $ do+ Data.RAList.filter (\x -> x < 9) ra `shouldBe`+ (fromList [1..8] :: RAList Int)+ it "filters for alternating values" $ do+ Data.RAList.filter (\x -> x == 1) (fromList [1,2,1,2,1,2,1,2,1])+ `shouldBe` (fromList [1,1,1,1,1] :: RAList Int)+ it "filters out every value" $ do+ Data.RAList.filter (\x -> False) ra `shouldBe` (empty :: RAList Int)+ it "returns an empty list when given an empty list" $ do+ Data.RAList.filter (\x -> True) empty `shouldBe` (empty :: RAList Int)++ describe "RAList.partition" $ do+ let ra = fromList [1..9]+ it "partitions for the first element in a list" $ do+ Data.RAList.partition (\x -> x == 1) ra `shouldBe`+ ((fromList [1], fromList [2..9]) :: (RAList Int, RAList Int))+ it "partitions out the first element in a list" $ do+ Data.RAList.partition (\x -> x > 1) ra `shouldBe`+ ((fromList [2..9], fromList [1]) :: (RAList Int, RAList Int))+ it "partitions for the last element in a list" $ do+ Data.RAList.partition (\x -> x == 9) ra `shouldBe`+ ((fromList [9], fromList [1..8]) :: (RAList Int, RAList Int))+ it "partitions out the last element in a list" $ do+ Data.RAList.partition (\x -> x < 9) ra `shouldBe`+ ((fromList [1..8], fromList [9]) :: (RAList Int, RAList Int))+ it "partitions for alternating values" $ do+ Data.RAList.partition (\x -> x == 1) (fromList [1,2,1,2,1,2,1,2,1])+ `shouldBe` ((fromList [1,1,1,1,1], fromList [2,2,2,2]) ::+ (RAList Int, RAList Int))+ it "partitions out every value" $ do+ Data.RAList.partition (\x -> False) ra `shouldBe`+ ((empty, ra) :: (RAList Int, RAList Int))+ it "returns an empty list when given an empty list" $ do+ Data.RAList.partition (\x -> True) empty `shouldBe`+ ((empty, empty) :: (RAList Int, RAList Int))++ describe "zip functions" $ do+ let ra1 = (fromList [1..9])+ let ra2 = (fromList ['a','b','c','d','e','f','g','h','i'])+ let ra3 = (fromList ([(1,'a'), (2,'b'), (3,'c'),(4,'d'),(5,'e'),(6,'f'),(7,'g'),(8,'h'),(9,'i')]))+ describe "RAList.zip" $ do+ it "can zip two lists of length 9" $ do+ Data.RAList.zip ra1 ra2 `shouldBe` (ra3 :: RAList (Int, Char))+ it "can zip two lists of length 3" $ do+ Data.RAList.zip (Data.RAList.take 3 ra1) (Data.RAList.take 3 ra2)+ `shouldBe`+ ((Data.RAList.take 3 ra3) :: RAList (Int, Char))+ it "can zip two lists of length 1" $ do+ Data.RAList.zip (Data.RAList.take 1 ra1) (Data.RAList.take 2 ra2)+ `shouldBe`+ (Data.RAList.take 1 ra3 :: RAList (Int,Char))+ it "can zip two lists of different lengths" $ do+ Data.RAList.zip ra1 (Data.RAList.take 5 ra2) `shouldBe`+ (Data.RAList.take 5 ra3 :: RAList (Int, Char))+ it "can zip a list to an empty list" $ do+ Data.RAList.zip empty ra2 `shouldBe` (empty :: RAList (Int, Char))+ it "can zip two empty lists" $ do+ Data.RAList.zip empty empty `shouldBe` (empty :: RAList (Int, Char))+ describe "RAList.unzip" $ do+ it "can unzip two lists of length 9" $ do+ Data.RAList.unzip ra3 `shouldBe`+ ((ra1,ra2) :: (RAList Int, RAList Char))+ it "can unzip two lists of length 3" $ do+ Data.RAList.unzip (Data.RAList.take 3 ra3) `shouldBe`+ (((Data.RAList.take 3 ra1),(Data.RAList.take 3 ra2)) ::+ (RAList Int, RAList Char))+ it "can unzip two lists of length 1" $ do+ Data.RAList.unzip (Data.RAList.take 1 ra3) `shouldBe`+ (((Data.RAList.take 1 ra1), (Data.RAList.take 1 ra2)) ::+ (RAList Int, RAList Char))+ describe "RAList.zipWith" $ do+ let ra1 = fromList [1..9]+ let ra2 = Data.RAList.replicate 9 1+ let ra3 = fromList [2,3..10]+ let f = (\x y -> x + y)+ it "can zip two lists of length 9" $ do+ Data.RAList.zipWith f ra1 ra2 `shouldBe` (ra3 :: RAList Int)+ it "cannp.zipWith two lists of length 3" $ do+ Data.RAList.zipWith f (Data.RAList.take 3 ra1) (Data.RAList.take 3 ra2)+ `shouldBe`+ ((Data.RAList.take 3 ra3) :: RAList Int)+ it "can zip two lists of length 1" $ do+ Data.RAList.zipWith f (Data.RAList.take 1 ra1) (Data.RAList.take 2 ra2)+ `shouldBe`+ (Data.RAList.take 1 ra3 :: RAList Int)+ it "can zip two lists of different lengths" $ do+ Data.RAList.zipWith f ra1 (Data.RAList.take 5 ra2) `shouldBe`+ (Data.RAList.take 5 ra3 :: RAList Int)+ it "can zip a list to an empty list" $ do+ Data.RAList.zipWith f empty ra2 `shouldBe` (empty :: RAList Int)+ it "can zip two empty lists" $ do+ Data.RAList.zipWith f empty empty `shouldBe`+ (empty :: RAList Int)++ describe "RAList.update" $ do+ let ra3 = fromList [1..3]+ let ra9 = fromList [1..9]+ it "can update the only value in a list" $ do+ Data.RAList.update 0 2 (fromList [1]) `shouldBe`+ (fromList [2] :: RAList Int)+ it "can update the first value in a list of length 3" $ do+ Data.RAList.update 0 4 ra3 `shouldBe` (fromList [4,2,3] :: RAList Int)+ it "can update the last value in a list of length 3" $ do+ Data.RAList.update 2 4 ra3 `shouldBe` (fromList [1,2,4] :: RAList Int)+ it "can update the first value in a list of length 9" $ do+ Data.RAList.update 0 10 ra9 `shouldBe`+ (fromList [10,2,3,4,5,6,7,8,9] :: RAList Int)+ it "can update the second value in a list of length 9" $ do+ Data.RAList.update 1 10 ra9 `shouldBe`+ (fromList [1,10,3,4,5,6,7,8,9] :: RAList Int)+ it "can update the third value in a list of length 9" $ do+ Data.RAList.update 2 10 ra9 `shouldBe`+ (fromList [1,2,10,4,5,6,7,8,9] :: RAList Int)+ it "can update the fourth value in a list of length 9" $ do+ Data.RAList.update 3 10 ra9 `shouldBe`+ (fromList [1,2,3,10,5,6,7,8,9])+ it "can update the last value in a list of length 9" $ do+ Data.RAList.update 8 10 ra9 `shouldBe`+ (fromList [1,2,3,4,5,6,7,8,10])+ it "throws an error when trying to update an index that is too large" $ do+ evaluate (Data.RAList.update 10 10 ra9 )`shouldThrow` anyException+ it "throws an error when trying to update an empty list" $ do+ evaluate (Data.RAList.update 0 0 empty) `shouldThrow` anyException++ describe "RAList.toList" $ do+ it "converts a list of length 1" $ do+ toList (fromList [1]) `shouldBe` ([1] :: [Int])+ it "converts a list of length 3" $ do+ toList (fromList[1..3]) `shouldBe` ([1..3] :: [Int])+ it "converts a list of length 9" $ do+ toList (fromList [1..9]) `shouldBe` ([1..9] :: [Int])+ it "converts an empty list" $ do+ toList (empty) `shouldBe` ([] :: [Int])+