rrb-vector-0.1.0.0: test/Spec.hs
import Data.Foldable (toList)
import Data.List (uncons)
import Test.Hspec
import Test.Hspec.QuickCheck
import Test.QuickCheck
import qualified Data.RRBVector as V
import Data.RRBVector.Internal.Debug (fromListUnbalanced)
default (Int)
instance (Arbitrary a) => Arbitrary (V.Vector a) where
arbitrary = oneof [V.fromList <$> arbitrary, fromListUnbalanced <$> arbitrary]
lookupList :: Int -> [a] -> Maybe a
lookupList i ls
| i < length ls = Just (ls !! i)
| otherwise = Nothing
updateList :: Int -> a -> [a] -> [a]
updateList i x ls
| i < length ls = let (left, _ : right) = splitAt i ls in left ++ (x : right)
| otherwise = ls
adjustList :: Int -> (a -> a) -> [a] -> [a]
adjustList i f ls
| i < length ls = let (left, x : right) = splitAt i ls in left ++ (f x : right)
| otherwise = ls
unsnoc :: [a] -> Maybe ([a], a)
unsnoc [] = Nothing
unsnoc ls = Just (init ls, last ls)
main :: IO ()
main = hspec . modifyMaxSuccess maxN . modifyMaxSize maxN $ do
prop "satisfies `fromList . toList == id`" $ \v -> V.fromList (toList v) === v
prop "satisfies `toList . fromList == id`" $ \ls -> toList (V.fromList ls) === ls
describe "lookup" $ do
prop "gets the element at the index" $ \v (NonNegative i) -> V.lookup i v === lookupList i (toList v)
prop "returns Nothing for negative indices" $ \v (Negative i) -> V.lookup i v === Nothing
describe "update" $ do
prop "updates the element at the index" $ \v (NonNegative i) x -> toList (V.update i x v) === updateList i x (toList v)
prop "returns the vector for negative indices" $ \v (Negative i) x -> V.update i x v === v
describe "adjust" $ do
prop "adjusts the element at the index" $ \v (NonNegative i) -> toList (V.adjust i (+ 1) v) === adjustList i (+ 1) (toList v)
prop "returns the vector for negative indices" $ \v (Negative i) -> V.adjust i (+ 1) v === v
describe "><" $ do
prop "concatenates two vectors" $ \v1 v2 -> toList (v1 V.>< v2) === toList v1 ++ toList v2
prop "works for the empty vector" $ \v -> (V.empty V.>< v `shouldBe` v) .&&. (v V.>< V.empty `shouldBe` v)
describe "|>" $ do
prop "appends an element" $ \v x -> toList (v V.|> x) === toList v ++ [x]
prop "works for the empty vector" $ \x -> V.empty V.|> x `shouldBe` V.singleton x
describe "<|" $ do
prop "prepends an element" $ \x v -> toList (x V.<| v) === x : toList v
prop "works for the empty vector" $ \x -> x V.<| V.empty `shouldBe` V.singleton x
describe "take" $ do
prop "takes n elements" $ \v (Positive n) -> toList (V.take n v) === take n (toList v)
prop "returns the empty vector for non-positive n" $ \v (NonPositive n) -> V.take n v === V.empty
describe "drop" $ do
prop "drops n elements" $ \v (Positive n) -> toList (V.drop n v) === drop n (toList v)
prop "does nothing for non-positive n" $ \v (NonPositive n) -> V.drop n v === v
describe "viewl" $ do
prop "works like uncons" $ \v -> fmap (\(x, xs) -> (x, toList xs)) (V.viewl v) === uncons (toList v)
prop "works for the empty vector" $ V.viewl V.empty `shouldBe` Nothing
describe "viewr" $ do
prop "works like unsnoc" $ \v -> fmap (\(xs, x) -> (toList xs, x)) (V.viewr v) === unsnoc (toList v)
prop "works for the empty vector" $ V.viewr V.empty `shouldBe` Nothing
describe "map" $ do
prop "maps over the vector" $ \v -> toList (V.map (+ 1) v) === map (+ 1) (toList v)
where
maxN = const 10_000