pvector-0.1.0.0: test/PersistentVectorSpec.hs
module PersistentVectorSpec (spec) where
import Data.Foldable (foldl')
import Data.Function ((&))
import Data.Primitive.SmallArray
import Data.Vector.Persistent (Vector)
import qualified Data.Vector.Persistent.Internal as Vector
import Data.Vector.Persistent.Internal.Array
import GHC.Exts (fromList, toList)
import Test.Hspec
import Test.Hspec.QuickCheck
import Test.QuickCheck
spec :: Spec
spec = parallel $ do
prop "toList fromList identity" $ \(l :: [Int]) ->
l === toList (fromList @(Vector _) l)
prop "fmap" fmapProp
prop "foldr" $ \(l :: [Int]) ->
foldr (:) [] l === foldr (:) [] (fromList @(Vector _) l)
prop "foldl" $ \(l :: [Int]) ->
foldl (flip (:)) [] l === foldl (flip (:)) [] (fromList @(Vector _) l)
it "update bad" $
propUpdate
64
0
((repeat 0 & take 64) ++ [1] ++ (repeat 0 & take 32))
-- this is somehow broken
prop "update" propUpdate
-- prop "update" $ \(ix :: Int) (a :: Int) (l :: [Int]) ->
-- ix >= 0 ==> do
-- let arr = fromList @(Array _) l
-- arr'
-- | ix >= sizeofSmallArray arr = arr
-- | otherwise = updateSmallArray arr ix a
-- toList arr' == toList (Vector.update ix a $ fromList @(Vector _) l)
prop "traverse" $ \(l :: [Int]) -> do
let go a = ([a], a)
fmap toList (traverse go (fromList @(Vector _) l)) === traverse go l
prop "index" indexProp
it "index weierd" $ indexProp 9 [1 :: Int .. 15]
prop "eq self" $ \(l :: [Int]) ->
fromList @(Vector _) l === fromList l
prop "eq" $ \(l :: [Int]) (l' :: [Int]) ->
(l == l') === (fromList @(Vector _) l == fromList @(Vector _) l')
prop "mappend" $ \(l :: [Int]) (l' :: [Int]) ->
l <> l' === toList (fromList @(Vector _) l <> fromList @(Vector _) l')
it "unsnoc bad" $ unsnocProp (replicate 65 0) 1
prop "unsnoc" unsnocProp
prop "snoc unsnoc" snocUnsnocProp
describe "indexed" $ do
prop "imap" $ \(l :: [Int]) ->
zip [0 :: Int ..] l === toList (Vector.imap (,) (fromList @(Vector _) l))
propUpdate :: Int -> Int -> [Int] -> Property
propUpdate ix a l =
ix >= 0 ==> do
let arr = fromList @(Array _) l
arr'
| ix >= sizeofSmallArray arr = arr
| otherwise = updateSmallArray arr ix a
toList arr' === toList (Vector.update ix a $ fromList @(Vector _) l)
fmapProp :: [Int] -> Property
fmapProp l = do
let vec = fmap (+ 20) (fromList @(Vector _) l)
res = toList vec
map (+ 20) l === res
snocUnsnocProp :: Int -> Bool
snocUnsnocProp times = do
Vector.null
. unsnocTimes
. snocTimes
. unsnocTimes
. snocTimes
$ Vector.empty
where
snocTimes vec = foldl' Vector.snoc vec [1 .. times]
unsnocTimes vec = foldl' (\vec _ -> unsnoc' vec) vec [1 .. times]
unsnocProp :: [Int] -> Int -> Property
unsnocProp l i = do
let l' = reverse $ drop i $ reverse l
vec = fromList @(Vector _) l
vec' =
foldl'
( \vec _ -> case Vector.unsnoc vec of
Nothing -> Vector.empty
Just (vec, _) -> vec
)
vec
[1 .. i]
l' === toList vec'
unsnoc' :: Vector a -> Vector a
unsnoc' vec = case Vector.unsnoc vec of
Just (vec, _) -> vec
_ -> error "empty vector"
indexProp :: Int -> [Int] -> Property
indexProp ix l = do
let indexMaybeList :: [a] -> Int -> Maybe a
indexMaybeList xs n
| n < 0 = Nothing
-- Definition adapted from GHC.List
| otherwise =
foldr
( \x r k -> case k of
0 -> Just x
_ -> r (k - 1)
)
(const Nothing)
xs
n
vec = fromList @(Vector _) l
indexMaybeList l ix === Vector.lookup ix vec