diff --git a/.github/workflows/haskell.yaml b/.github/workflows/haskell.yaml index 9057477..2656d83 100644 --- a/.github/workflows/haskell.yaml +++ b/.github/workflows/haskell.yaml @@ -8,6 +8,7 @@ jobs: build: runs-on: ubuntu-latest strategy: + fail-fast: false matrix: ghc: ['8.4', '8.6', '8.8', '8.10', '9.0', '9.2', '9.4', '9.6'] steps: @@ -18,4 +19,4 @@ jobs: - name: Build run: cabal build - name: Test - run: cabal test --test-show-details=direct + run: cabal test --enable-tests --test-show-details=direct diff --git a/CHANGELOG.md b/CHANGELOG.md index 595c338..a238138 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ -# 0.2.0.0 +# 0.2.0.1 - October 2023 + +* Support `primitive-0.9` and `deepseq-1.5` + +# 0.2.0.0 - February 2023 * Add `map'` & `unzipWith` * Make `zip` & `unzip` more strict @@ -7,6 +11,7 @@ * Implement `ifoldMap` in the `FoldableWithIndex` instance * Implement `fail` in the `Monad` instance * Add `Shift`, `Tree` and unidirectional pattern synonyms for `Vector` and `Tree` to `Data.RRBVector.Internal.Debug` +* Support `primitive-0.8` * Test typeclass laws diff --git a/rrb-vector.cabal b/rrb-vector-strict.cabal similarity index 72% rename from rrb-vector.cabal rename to rrb-vector-strict.cabal index 57cf3ef..614fdb8 100644 --- a/rrb-vector.cabal +++ b/rrb-vector-strict.cabal @@ -1,5 +1,5 @@ -name: rrb-vector -version: 0.2.0.0 +name: rrb-vector-strict +version: 0.2.0.1 synopsis: Efficient RRB-Vectors description: An RRB-Vector is an efficient sequence data structure. @@ -9,6 +9,8 @@ description: . @Seq a@ is a container with a very similar API. RRB-Vectors are generally faster for indexing and iteration, while sequences are faster for access to the front/back (amortized \(O(1)\)). + + This package provides a variant of this data structure that is guaranteed to be value strict. homepage: https://github.com/konsumlamm/rrb-vector bug-reports: https://github.com/konsumlamm/rrb-vector/issues license: BSD3 @@ -28,25 +30,25 @@ tested-with: GHC == 8.8.4 GHC == 8.10.7 GHC == 9.0.2 - GHC == 9.2.7 - GHC == 9.4.4 - GHC == 9.6.1 + GHC == 9.2.8 + GHC == 9.4.7 + GHC == 9.6.3 source-repository head type: git - location: https://github.com/konsumlamm/rrb-vector.git + location: https://github.com/tracsis/rrb-vector-strict.git library hs-source-dirs: src exposed-modules: - Data.RRBVector - Data.RRBVector.Internal.Debug + Data.RRBVector.Strict + Data.RRBVector.Strict.Internal.Debug other-modules: - Data.RRBVector.Internal - Data.RRBVector.Internal.Array - Data.RRBVector.Internal.Buffer - Data.RRBVector.Internal.IntRef - build-depends: base >= 4.11 && < 5, deepseq ^>= 1.4.3, indexed-traversable ^>= 0.1, primitive >= 0.7 && < 0.9 + Data.RRBVector.Strict.Internal + Data.RRBVector.Strict.Internal.Array + Data.RRBVector.Strict.Internal.Buffer + Data.RRBVector.Strict.Internal.IntRef + build-depends: base >= 4.11 && < 5, deepseq >= 1.4.3 && < 1.6, indexed-traversable ^>= 0.1, primitive >= 0.7 && < 0.10 ghc-options: -O2 -Wall -Wno-name-shadowing -Werror=missing-methods -Werror=missing-fields default-language: Haskell2010 @@ -59,7 +61,7 @@ test-suite test Strictness type: exitcode-stdio-1.0 ghc-options: -Wall -Wno-orphans -Wno-type-defaults - build-depends: base, deepseq, quickcheck-classes-base, rrb-vector, tasty, tasty-quickcheck + build-depends: base, deepseq, quickcheck-classes-base, rrb-vector-strict, tasty, tasty-quickcheck if impl(ghc >= 8.6) build-depends: nothunks default-language: Haskell2010 @@ -71,5 +73,5 @@ benchmark rrb-bench type: exitcode-stdio-1.0 default-language: Haskell2010 ghc-options: -O2 - build-depends: base, rrb-vector, tasty-bench + build-depends: base, rrb-vector-strict, tasty-bench default-extensions: ExtendedDefaultRules diff --git a/src/Data/RRBVector.hs b/src/Data/RRBVector/Strict.hs similarity index 96% rename from src/Data/RRBVector.hs rename to src/Data/RRBVector/Strict.hs index 10ed1c5..917f011 100644 --- a/src/Data/RRBVector.hs +++ b/src/Data/RRBVector/Strict.hs @@ -18,7 +18,7 @@ The implementation uses Relaxed-Radix-Balanced trees, as described by Currently, a branching factor of 16 is used. The tree is strict in its spine, but lazy in its elements. -} -module Data.RRBVector +module Data.RRBVector.Strict ( Vector -- * Construction , empty, singleton, fromList, replicate @@ -51,4 +51,4 @@ import Data.Foldable.WithIndex import Data.Functor.WithIndex import Data.Traversable.WithIndex -import Data.RRBVector.Internal +import Data.RRBVector.Strict.Internal diff --git a/src/Data/RRBVector/Internal.hs b/src/Data/RRBVector/Strict/Internal.hs similarity index 99% rename from src/Data/RRBVector/Internal.hs rename to src/Data/RRBVector/Strict/Internal.hs index a2ffc95..e96267a 100644 --- a/src/Data/RRBVector/Internal.hs +++ b/src/Data/RRBVector/Strict/Internal.hs @@ -5,7 +5,7 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} -module Data.RRBVector.Internal +module Data.RRBVector.Strict.Internal ( Vector(..) , Tree(..) , Shift @@ -30,7 +30,11 @@ module Data.RRBVector.Internal , zip, zipWith, unzip, unzipWith ) where +#if !(MIN_VERSION_base(4,18,0)) import Control.Applicative (Alternative, liftA2) +#else +import Control.Applicative (Alternative) +#endif import qualified Control.Applicative import Control.DeepSeq import Control.Monad (when, MonadPlus) @@ -57,8 +61,8 @@ import Data.Foldable.WithIndex import Data.Traversable.WithIndex import Data.Primitive.PrimArray hiding (sizeofPrimArray) -- use @length@ of the @A.Array@ instead -import qualified Data.RRBVector.Internal.Array as A -import qualified Data.RRBVector.Internal.Buffer as Buffer +import qualified Data.RRBVector.Strict.Internal.Array as A +import qualified Data.RRBVector.Strict.Internal.Buffer as Buffer infixr 5 >< infixr 5 <| @@ -144,7 +148,7 @@ computeSizes :: Shift -> A.Array (Tree a) -> Tree a computeSizes !sh arr | isBalanced = Balanced arr | otherwise = runST $ do - sizes <- newPrimArray (length arr) + sizes <- newPrimArray len let loop acc i | i < len = let size = treeSize (down sh) (A.index arr i) diff --git a/src/Data/RRBVector/Internal/Array.hs b/src/Data/RRBVector/Strict/Internal/Array.hs similarity index 78% rename from src/Data/RRBVector/Internal/Array.hs rename to src/Data/RRBVector/Strict/Internal/Array.hs index 2282c01..3123fdd 100644 --- a/src/Data/RRBVector/Internal/Array.hs +++ b/src/Data/RRBVector/Strict/Internal/Array.hs @@ -1,4 +1,5 @@ {-# LANGUAGE BangPatterns #-} +{-# LANGUAGE CPP #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE UnboxedTuples #-} @@ -10,7 +11,7 @@ -- -- __Warning:__ No bound checks are performed! -module Data.RRBVector.Internal.Array +module Data.RRBVector.Strict.Internal.Array ( Array, MutableArray , ifoldrStep, ifoldlStep, ifoldrStep', ifoldlStep' , empty, singleton, from2 @@ -28,7 +29,9 @@ module Data.RRBVector.Internal.Array , freeze, thaw ) where -import Control.Applicative (Applicative(liftA2)) +#if !(MIN_VERSION_base(4,18,0)) +import Control.Applicative (liftA2) +#endif import Control.DeepSeq (NFData(..)) import Control.Monad (when) import Control.Monad.ST @@ -111,20 +114,20 @@ empty :: Array a empty = Array 0 0 $ runSmallArray (newSmallArray 0 uninitialized) singleton :: a -> Array a -singleton x = Array 0 1 $ runSmallArray (newSmallArray 1 x) +singleton !x = Array 0 1 $ runSmallArray (newSmallArray 1 x) from2 :: a -> a -> Array a -from2 x y = Array 0 2 $ runSmallArray $ do +from2 !x !y = Array 0 2 $ runSmallArray $ do sma <- newSmallArray 2 x writeSmallArray sma 1 y pure sma replicate :: Int -> a -> Array a -replicate n x = Array 0 n $ runSmallArray (newSmallArray n x) +replicate n !x = Array 0 n $ runSmallArray (newSmallArray n x) -- > replicateSnoc n x y = snoc (replicate n x) y replicateSnoc :: Int -> a -> a -> Array a -replicateSnoc n x y = Array 0 len $ runSmallArray $ do +replicateSnoc n !x !y = Array 0 len $ runSmallArray $ do sma <- newSmallArray len x writeSmallArray sma n y pure sma @@ -135,17 +138,13 @@ index :: Array a -> Int -> a index (Array start _ arr) idx = indexSmallArray arr (start + idx) update :: Array a -> Int -> a -> Array a -update (Array start len sa) idx x = Array 0 len $ runSmallArray $ do +update (Array start len sa) idx !x = Array 0 len $ runSmallArray $ do sma <- thawSmallArray sa start len writeSmallArray sma idx x pure sma adjust :: Array a -> Int -> (a -> a) -> Array a -adjust (Array start len sa) idx f = Array 0 len $ runSmallArray $ do - sma <- thawSmallArray sa start len - x <- indexSmallArrayM sa (start + idx) - writeSmallArray sma idx (f x) - pure sma +adjust = adjust' adjust' :: Array a -> Int -> (a -> a) -> Array a adjust' (Array start len sa) idx f = Array 0 len $ runSmallArray $ do @@ -170,17 +169,17 @@ last :: Array a -> a last arr = index arr (length arr - 1) snoc :: Array a -> a -> Array a -snoc (Array _ len arr) x = Array 0 len' $ runSmallArray $ do +snoc (Array start len arr) !x = Array 0 len' $ runSmallArray $ do sma <- newSmallArray len' x - copySmallArray sma 0 arr 0 len + copySmallArray sma 0 arr start len pure sma where !len' = len + 1 cons :: Array a -> a -> Array a -cons (Array _ len arr) x = Array 0 len' $ runSmallArray $ do +cons (Array start len arr) !x = Array 0 len' $ runSmallArray $ do sma <- newSmallArray len' x - copySmallArray sma 1 arr 0 len + copySmallArray sma 1 arr start len pure sma where !len' = len + 1 @@ -195,15 +194,7 @@ Array start1 len1 arr1 ++ Array start2 len2 arr2 = Array 0 len' $ runSmallArray !len' = len1 + len2 map :: (a -> b) -> Array a -> Array b -map f (Array start len arr) = Array 0 len $ runSmallArray $ do - sma <- newSmallArray len uninitialized - -- i is the index in arr, j is the index in sma - let loop i j = when (j < len) $ do - x <- indexSmallArrayM arr i - writeSmallArray sma j (f x) - loop (i + 1) (j + 1) - loop start 0 - pure sma +map = map' map' :: (a -> b) -> Array a -> Array b map' f (Array start len arr) = Array 0 len $ runSmallArray $ do @@ -218,15 +209,7 @@ map' f (Array start len arr) = Array 0 len $ runSmallArray $ do -- helper function for implementing imap imapStep :: Int -> (a -> Int) -> (Int -> a -> b) -> Array a -> Array b -imapStep i0 step f (Array start len arr) = Array 0 len $ runSmallArray $ do - sma <- newSmallArray len uninitialized - -- i is the index in arr, j is the index in sma, k is the index for f - let loop !i !j !k = when (j < len) $ do - x <- indexSmallArrayM arr i - writeSmallArray sma j (f k x) - loop (i + 1) (j + 1) (k + step x) - loop start 0 i0 - pure sma +imapStep = imapStep' -- helper function for implementing imap imapStep' :: Int -> (a -> Int) -> (Int -> a -> b) -> Array a -> Array b @@ -247,9 +230,9 @@ unzipWith f (Array start len arr) = runST $ do -- i is the index in arr, j is the index in sma1/sma2 let loop i j = when (j < len) $ do val <- indexSmallArrayM arr i - let !(x, y) = f val - writeSmallArray sma1 j x - writeSmallArray sma2 j y + let (x, y) = f val + writeSmallArray sma1 j $! x + writeSmallArray sma2 j $! y loop (i + 1) (j + 1) loop start 0 arr1 <- unsafeFreezeSmallArray sma1 @@ -262,12 +245,7 @@ runSTA :: Int -> STA a -> Array a runSTA len (STA m) = Array 0 len (runST $ newSmallArray len uninitialized >>= m) traverse :: (Applicative f) => (a -> f b) -> Array a -> f (Array b) -traverse f (Array start len arr) = - -- i is the index in arr, j is the index in sma - let go i j - | j == len = pure $ STA unsafeFreezeSmallArray - | (# x #) <- indexSmallArray## arr i = liftA2 (\y (STA m) -> STA $ \sma -> writeSmallArray sma j y *> m sma) (f x) (go (i + 1) (j + 1)) - in runSTA len <$> go start 0 +traverse = traverse' traverse' :: (Applicative f) => (a -> f b) -> Array a -> f (Array b) traverse' f (Array start len arr) = @@ -279,12 +257,7 @@ traverse' f (Array start len arr) = -- helper function for implementing itraverse itraverseStep :: (Applicative f) => Int -> (a -> Int) -> (Int -> a -> f b) -> Array a -> f (Array b) -itraverseStep i0 step f (Array start len arr) = - -- i is the index in arr, j is the index in sma, k is the index for f - let go !i !j !k - | j == len = pure $ STA unsafeFreezeSmallArray - | (# x #) <- indexSmallArray## arr i = liftA2 (\y (STA m) -> STA $ \sma -> writeSmallArray sma j y *> m sma) (f k x) (go (i + 1) (j + 1) (k + step x)) - in runSTA len <$> go start 0 i0 +itraverseStep = itraverseStep' -- helper function for implementing itraverse itraverseStep' :: (Applicative f) => Int -> (a -> Int) -> (Int -> a -> f b) -> Array a -> f (Array b) @@ -302,7 +275,7 @@ read :: MutableArray s a -> Int -> ST s a read (MutableArray start _ arr) idx = readSmallArray arr (start + idx) write :: MutableArray s a -> Int -> a -> ST s () -write (MutableArray start _ arr) idx = writeSmallArray arr (start + idx) +write (MutableArray start _ arr) idx !x = writeSmallArray arr (start + idx) x freeze :: MutableArray s a -> Int -> Int -> ST s (Array a) freeze (MutableArray start _ arr) idx len = Array 0 len <$> freezeSmallArray arr (start + idx) len diff --git a/src/Data/RRBVector/Internal/Buffer.hs b/src/Data/RRBVector/Strict/Internal/Buffer.hs similarity index 86% rename from src/Data/RRBVector/Internal/Buffer.hs rename to src/Data/RRBVector/Strict/Internal/Buffer.hs index 7bd671d..eb713a1 100644 --- a/src/Data/RRBVector/Internal/Buffer.hs +++ b/src/Data/RRBVector/Strict/Internal/Buffer.hs @@ -2,8 +2,9 @@ -- -- A 'Buffer' is an array with a fixed capacity, used to build up 'Data.RRBVector.Internal.Array.Array's. -- It is used in the implementation of 'Data.RRBVector.fromList' and 'Data.RRBVector.><'. +{-# LANGUAGE BangPatterns #-} -module Data.RRBVector.Internal.Buffer +module Data.RRBVector.Strict.Internal.Buffer ( Buffer , new , push @@ -13,8 +14,8 @@ module Data.RRBVector.Internal.Buffer import Control.Monad.ST -import Data.RRBVector.Internal.IntRef -import qualified Data.RRBVector.Internal.Array as A +import Data.RRBVector.Strict.Internal.IntRef +import qualified Data.RRBVector.Strict.Internal.Array as A -- | A mutable array buffer with a fixed capacity. data Buffer s a = Buffer !(A.MutableArray s a) !(IntRef s) @@ -29,7 +30,7 @@ new capacity = do -- | \(O(1)\). Push a new element onto the buffer. -- The size of the buffer must not exceed the capacity, but this is not checked. push :: Buffer s a -> a -> ST s () -push (Buffer buffer offset) x = do +push (Buffer buffer offset) !x = do idx <- readIntRef offset A.write buffer idx x writeIntRef offset (idx + 1) diff --git a/src/Data/RRBVector/Internal/Debug.hs b/src/Data/RRBVector/Strict/Internal/Debug.hs similarity index 90% rename from src/Data/RRBVector/Internal/Debug.hs rename to src/Data/RRBVector/Strict/Internal/Debug.hs index 5f5924c..7f557e8 100644 --- a/src/Data/RRBVector/Internal/Debug.hs +++ b/src/Data/RRBVector/Strict/Internal/Debug.hs @@ -4,7 +4,7 @@ This module contains some debug utilities. It should only be used for debugging/testing purposes. -} -module Data.RRBVector.Internal.Debug +module Data.RRBVector.Strict.Internal.Debug ( showTree , fromListUnbalanced , pattern Empty, pattern Root @@ -17,10 +17,10 @@ import Data.Foldable (toList) import Data.List (intercalate) import Data.Primitive.PrimArray (PrimArray, primArrayToList) -import Data.RRBVector.Internal hiding (Empty, Root, Balanced, Unbalanced, Leaf) -import qualified Data.RRBVector.Internal as RRB -import Data.RRBVector.Internal.Array (Array) -import qualified Data.RRBVector.Internal.Buffer as Buffer +import Data.RRBVector.Strict.Internal hiding (Empty, Root, Balanced, Unbalanced, Leaf) +import qualified Data.RRBVector.Strict.Internal as RRB +import Data.RRBVector.Strict.Internal.Array (Array) +import qualified Data.RRBVector.Strict.Internal.Buffer as Buffer -- | \(O(n)\). Show the underlying tree of a vector. showTree :: (Show a) => Vector a -> String diff --git a/src/Data/RRBVector/Internal/IntRef.hs b/src/Data/RRBVector/Strict/Internal/IntRef.hs similarity index 95% rename from src/Data/RRBVector/Internal/IntRef.hs rename to src/Data/RRBVector/Strict/Internal/IntRef.hs index 64fa5c2..1f27b7f 100644 --- a/src/Data/RRBVector/Internal/IntRef.hs +++ b/src/Data/RRBVector/Strict/Internal/IntRef.hs @@ -2,7 +2,7 @@ -- -- It works like "Data.STRef", but is specialized to 'Int' and more efficient. -module Data.RRBVector.Internal.IntRef +module Data.RRBVector.Strict.Internal.IntRef ( IntRef , newIntRef , readIntRef diff --git a/test/Arbitrary.hs b/test/Arbitrary.hs index 2d07e53..fdc3009 100644 --- a/test/Arbitrary.hs +++ b/test/Arbitrary.hs @@ -1,14 +1,17 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleInstances #-} module Arbitrary where +#if !(MIN_VERSION_base(4,18,0)) import Control.Applicative (liftA2) +#endif import Data.Foldable (toList) import Test.Tasty.QuickCheck -import qualified Data.RRBVector as V -import Data.RRBVector.Internal.Debug +import qualified Data.RRBVector.Strict as V +import Data.RRBVector.Strict.Internal.Debug builders :: [[a] -> V.Vector a] builders = [V.fromList, fromListUnbalanced] diff --git a/test/Main.hs b/test/Main.hs index 38694f4..7f95776 100644 --- a/test/Main.hs +++ b/test/Main.hs @@ -1,5 +1,3 @@ -{-# LANGUAGE BangPatterns #-} - import Test.Tasty import Test.Tasty.QuickCheck diff --git a/test/Properties.hs b/test/Properties.hs index d6fd58a..62d188a 100644 --- a/test/Properties.hs +++ b/test/Properties.hs @@ -1,14 +1,18 @@ +{-# LANGUAGE CPP #-} + module Properties ( properties ) where +#if !(MIN_VERSION_base(4,18,0)) import Control.Applicative (liftA2) +#endif import Data.Foldable (Foldable(..)) import Data.List (uncons) import Data.Proxy (Proxy(..)) import Prelude hiding ((==)) -- use @===@ instead -import qualified Data.RRBVector as V +import qualified Data.RRBVector.Strict as V import Test.QuickCheck.Classes.Base import Test.Tasty import Test.Tasty.QuickCheck @@ -146,6 +150,7 @@ properties = testGroup "properties" ] , instances , laws + , issues ] instances :: TestTree @@ -215,3 +220,12 @@ laws = testGroup "typeclass laws" , localOption (QuickCheckTests 500) . localOption (QuickCheckMaxSize 5000) . testLaws $ monadZipLaws proxyV , localOption (QuickCheckMaxSize 100) . testLaws $ traversableLaws proxyV ] + +-- old issues, to avoid regressions +issues :: TestTree +issues = testGroup "issues" + -- https://github.com/konsumlamm/rrb-vector/issues/10 + [ testProperty "#10" $ \x v -> case V.viewl v of + Nothing -> property True + Just (_, v') -> x V.<| v' === V.update 0 x v + ] diff --git a/test/Strictness.hs b/test/Strictness.hs index b1100d0..f4bf2f1 100644 --- a/test/Strictness.hs +++ b/test/Strictness.hs @@ -8,11 +8,11 @@ module Strictness import Control.DeepSeq (deepseq) import Data.Foldable (foldr', foldl', toList) import Data.Maybe (isNothing) -import Data.RRBVector.Internal.Debug +import Data.RRBVector.Strict.Internal.Debug import NoThunks.Class #endif -import qualified Data.RRBVector as V +import qualified Data.RRBVector.Strict as V import Test.Tasty import Test.Tasty.QuickCheck @@ -48,27 +48,32 @@ initVector v = case V.viewr v of Just (xs, _) -> Just xs #endif +inc :: Int -> Int +inc x = x + 1 +{-# NOINLINE inc#-} + strictness :: TestTree strictness = testGroup "strictness" + [ #ifdef VERSION_nothunks - [ localOption (QuickCheckTests 500) $ testGroup "nf" + localOption (QuickCheckTests 500) $ testGroup "nf" [ testProperty "empty" $ testNF (V.empty :: V.Vector Int) - , testProperty "singleton" $ testNF (V.singleton 42) - , testProperty "fromList" $ \ls -> ls `deepseq` testNF (V.fromList ls) - , testProperty "replicate" $ \n -> testNF (V.replicate n 42) - , testProperty "update" $ \v (NonNegative i) -> v `deepseq` testNF (V.update i 42 v) - , testProperty "adjust'" $ \v (NonNegative i) -> v `deepseq` testNF (V.adjust' i (+ 1) v) - , testProperty "<|" $ \v -> v `deepseq` testNF (42 V.<| v) - , testProperty "|>" $ \v -> v `deepseq` testNF (v V.|> 42) + , testProperty "singleton" $ testNF (V.singleton $ inc 42) + , testProperty "fromList" $ \ls -> let ls' = map inc ls in testNF (V.fromList ls') + , testProperty "replicate" $ \n -> testNF (V.replicate n $ inc 43) + , testProperty "update" $ \v (NonNegative i) -> v `deepseq` testNF (V.update i (inc 44) v) + , testProperty "adjust'" $ \v (NonNegative i) -> v `deepseq` testNF (V.adjust' i inc v) + , testProperty "<|" $ \v -> v `deepseq` testNF (inc 45 V.<| v) + , testProperty "|>" $ \v -> v `deepseq` testNF (v V.|> inc 46) , testProperty "><" $ \v1 v2 -> v1 `deepseq` v2 `deepseq` testNF (v1 V.>< v2) , testProperty "take" $ \v n -> v `deepseq` testNF (V.take n v) , testProperty "drop" $ \v n -> v `deepseq` testNF (V.drop n v) , testProperty "splitAt" $ \v n -> v `deepseq` testNF (V.splitAt n v) - , testProperty "insertAt" $ \v i -> v `deepseq` testNF (V.insertAt i 42 v) + , testProperty "insertAt" $ \v i -> v `deepseq` testNF (V.insertAt i (inc 47) v) , testProperty "deleteAt" $ \v i -> v `deepseq` testNF (V.deleteAt i v) , testProperty "viewl (tail)" $ \v -> v `deepseq` testNF (tailVector v) , testProperty "viewr (init)" $ \v -> v `deepseq` testNF (initVector v) - , testProperty "map'" $ \v -> v `deepseq` testNF (V.map' (+ 1) v) + , testProperty "map'" $ \v -> v `deepseq` testNF (V.map' inc v) , testProperty "reverse" $ \v -> v `deepseq` testNF (V.reverse v) , testProperty "zip" $ \v1 v2 -> v1 `deepseq` v2 `deepseq` testNF (V.zip v1 v2) , testProperty "unzip" $ \v -> v `deepseq` testNF (V.unzip v) @@ -77,19 +82,5 @@ strictness = testGroup "strictness" , testProperty "ifoldr'" $ \v -> (v :: V.Vector Int) `deepseq` testNF (V.ifoldr' (const (:)) [] v) , testProperty "ifoldl'" $ \v -> (v :: V.Vector Int) `deepseq` testNF (V.ifoldl' (const (flip (:))) [] v) ] - , testGroup "bottom" -#else - [ testGroup "bottom" #endif - [ testProperty "singleton" $ V.singleton undefined `seq` () - , testProperty "fromList" $ \n -> V.fromList (replicate n undefined) `seq` () - , testProperty "replicate" $ \n -> V.replicate n undefined `seq` () - , testProperty "<|" $ \v -> undefined V.<| v `seq` () - , testProperty "|>" $ \v -> v V.|> undefined `seq` () - , testProperty "update" $ \v i -> V.update i undefined v `seq` () - , testProperty "adjust" $ \v i -> V.adjust i (const undefined) v `seq` () - , testProperty "insertAt" $ \v i -> V.insertAt i undefined v `seq` () - , testProperty "map" $ \v -> V.map (const undefined) v `seq` () - , testProperty "zipWith" $ \v1 v2 -> V.zipWith (\_ _ -> undefined) v1 v2 `seq` () - ] ]