1{-# LANGUAGE ConstraintKinds #-} 2module Tests.Vector.Property 3 ( CommonContext 4 , VanillaContext 5 , VectorContext 6 , testSanity 7 , testPolymorphicFunctions 8 , testTuplyFunctions 9 , testOrdFunctions 10 , testEnumFunctions 11 , testMonoidFunctions 12 , testFunctorFunctions 13 , testMonadFunctions 14 , testApplicativeFunctions 15 , testAlternativeFunctions 16 , testSequenceFunctions 17 , testBoolFunctions 18 , testNumFunctions 19 , testNestedVectorFunctions 20 , testDataFunctions 21 -- re-exports 22 , Data 23 , Random 24 , Test 25 ) where 26 27import Boilerplater 28import Utilities as Util hiding (limitUnfolds) 29 30import Control.Monad 31import Data.Functor.Identity 32import qualified Data.Traversable as T (Traversable(..)) 33import Data.Foldable (Foldable(foldMap)) 34import Data.Orphans () 35 36import qualified Data.Vector.Generic as V 37import qualified Data.Vector.Fusion.Bundle as S 38 39import Test.QuickCheck 40 41import Test.Tasty 42import Test.Tasty.QuickCheck hiding (testProperties) 43 44import Text.Show.Functions () 45import Data.List 46 47import Data.Monoid 48 49import qualified Control.Applicative as Applicative 50import System.Random (Random) 51 52import Data.Functor.Identity 53import Control.Monad.Trans.Writer 54 55import Control.Monad.Zip 56 57import Data.Data 58 59import qualified Data.List.NonEmpty as DLE 60import Data.Semigroup (Semigroup(..)) 61 62type CommonContext a v = (VanillaContext a, VectorContext a v) 63type VanillaContext a = ( Eq a , Show a, Arbitrary a, CoArbitrary a 64 , TestData a, Model a ~ a, EqTest a ~ Property) 65type VectorContext a v = ( Eq (v a), Show (v a), Arbitrary (v a), CoArbitrary (v a) 66 , TestData (v a), Model (v a) ~ [a], EqTest (v a) ~ Property, V.Vector v a) 67 68-- | migration hack for moving from TestFramework to Tasty 69type Test = TestTree 70-- TODO: implement Vector equivalents of list functions for some of the commented out properties 71 72-- TODO: add tests for the other extra functions 73-- IVector exports still needing tests: 74-- copy, 75-- new, 76-- unsafeSlice, unsafeIndex, 77 78testSanity :: forall a v. (CommonContext a v) => v a -> [Test] 79{-# INLINE testSanity #-} 80testSanity _ = [ 81 testProperty "fromList.toList == id" prop_fromList_toList, 82 testProperty "toList.fromList == id" prop_toList_fromList, 83 testProperty "unstream.stream == id" prop_unstream_stream, 84 testProperty "stream.unstream == id" prop_stream_unstream 85 ] 86 where 87 prop_fromList_toList (v :: v a) = (V.fromList . V.toList) v == v 88 prop_toList_fromList (l :: [a]) = ((V.toList :: v a -> [a]) . V.fromList) l == l 89 prop_unstream_stream (v :: v a) = (V.unstream . V.stream) v == v 90 prop_stream_unstream (s :: S.Bundle v a) = ((V.stream :: v a -> S.Bundle v a) . V.unstream) s == s 91 92testPolymorphicFunctions :: forall a v. (CommonContext a v, VectorContext Int v) => v a -> [Test] 93-- FIXME: inlining of unboxed properties blows up the memory during compilation. See #272 94--{-# INLINE testPolymorphicFunctions #-} 95testPolymorphicFunctions _ = $(testProperties [ 96 'prop_eq, 97 98 -- Length information 99 'prop_length, 'prop_null, 100 101 -- Indexing 102 'prop_index, 'prop_safeIndex, 'prop_head, 'prop_last, 103 'prop_unsafeIndex, 'prop_unsafeHead, 'prop_unsafeLast, 104 105 -- Monadic indexing (FIXME) 106 {- 'prop_indexM, 'prop_headM, 'prop_lastM, 107 'prop_unsafeIndexM, 'prop_unsafeHeadM, 'prop_unsafeLastM, -} 108 109 -- Subvectors (FIXME) 110 'prop_slice, 'prop_init, 'prop_tail, 'prop_take, 'prop_drop, 111 'prop_splitAt, 112 {- 'prop_unsafeSlice, 'prop_unsafeInit, 'prop_unsafeTail, 113 'prop_unsafeTake, 'prop_unsafeDrop, -} 114 115 -- Initialisation (FIXME) 116 'prop_empty, 'prop_singleton, 'prop_replicate, 117 'prop_generate, 'prop_iterateN, 'prop_iterateNM, 118 'prop_generateM, 'prop_replicateM, 119 120 -- Monadic initialisation (FIXME) 121 'prop_create, 'prop_createT, 122 123 -- Unfolding 124 'prop_unfoldr, 'prop_unfoldrN, 'prop_unfoldrExactN, 125 'prop_unfoldrM, 'prop_unfoldrNM, 'prop_unfoldrExactNM, 126 'prop_constructN, 'prop_constructrN, 127 128 -- Concatenation (FIXME) 129 'prop_cons, 'prop_snoc, 'prop_append, 130 'prop_concat, 131 132 -- Restricting memory usage 133 'prop_force, 134 135 136 -- Bulk updates (FIXME) 137 'prop_upd, 138 {- 'prop_update_, 139 'prop_unsafeUpd, 'prop_unsafeUpdate, 'prop_unsafeUpdate_, -} 140 141 -- Accumulations (FIXME) 142 'prop_accum, 143 {- 'prop_accumulate, 'prop_accumulate_, 144 'prop_unsafeAccum, 'prop_unsafeAccumulate, 'prop_unsafeAccumulate_, -} 145 146 -- Permutations 147 'prop_reverse, 'prop_backpermute, 148 {- 'prop_unsafeBackpermute, -} 149 150 -- Mapping 151 'prop_map, 'prop_imap, 'prop_concatMap, 152 153 -- Monadic mapping 154 'prop_mapM, 'prop_mapM_, 'prop_forM, 'prop_forM_, 155 'prop_imapM, 'prop_imapM_, 156 157 -- Zipping 158 'prop_zipWith, 'prop_zipWith3, 159 'prop_izipWith, 'prop_izipWith3, 160 'prop_izipWithM, 'prop_izipWithM_, 161 162 -- Monadic zipping 163 'prop_zipWithM, 'prop_zipWithM_, 164 165 -- Filtering 166 'prop_filter, 'prop_ifilter, 'prop_filterM, 167 'prop_uniq, 168 'prop_mapMaybe, 'prop_imapMaybe, 169 'prop_takeWhile, 'prop_dropWhile, 170 171 -- Paritioning 172 'prop_partition, {- 'prop_unstablePartition, -} 173 'prop_partitionWith, 174 'prop_span, 'prop_break, 175 176 -- Searching 177 'prop_elem, 'prop_notElem, 178 'prop_find, 'prop_findIndex, 'prop_findIndexR, 'prop_findIndices, 179 'prop_elemIndex, 'prop_elemIndices, 180 181 -- Folding 182 'prop_foldl, 'prop_foldl1, 'prop_foldl', 'prop_foldl1', 183 'prop_foldr, 'prop_foldr1, 'prop_foldr', 'prop_foldr1', 184 'prop_ifoldl, 'prop_ifoldl', 'prop_ifoldr, 'prop_ifoldr', 185 'prop_ifoldM, 'prop_ifoldM', 'prop_ifoldM_, 'prop_ifoldM'_, 186 187 -- Specialised folds 188 'prop_all, 'prop_any, 189 190 -- Scans 191 'prop_prescanl, 'prop_prescanl', 192 'prop_postscanl, 'prop_postscanl', 193 'prop_scanl, 'prop_scanl', 'prop_scanl1, 'prop_scanl1', 194 'prop_iscanl, 'prop_iscanl', 195 196 'prop_prescanr, 'prop_prescanr', 197 'prop_postscanr, 'prop_postscanr', 198 'prop_scanr, 'prop_scanr', 'prop_scanr1, 'prop_scanr1', 199 'prop_iscanr, 'prop_iscanr' 200 ]) 201 where 202 -- Prelude 203 prop_eq :: P (v a -> v a -> Bool) = (==) `eq` (==) 204 205 prop_length :: P (v a -> Int) = V.length `eq` length 206 prop_null :: P (v a -> Bool) = V.null `eq` null 207 208 prop_empty :: P (v a) = V.empty `eq` [] 209 prop_singleton :: P (a -> v a) = V.singleton `eq` Util.singleton 210 prop_replicate :: P (Int -> a -> v a) 211 = (\n _ -> n < 1000) ===> V.replicate `eq` replicate 212 prop_replicateM :: P (Int -> Writer [a] a -> Writer [a] (v a)) 213 = (\n _ -> n < 1000) ===> V.replicateM `eq` replicateM 214 prop_cons :: P (a -> v a -> v a) = V.cons `eq` (:) 215 prop_snoc :: P (v a -> a -> v a) = V.snoc `eq` snoc 216 prop_append :: P (v a -> v a -> v a) = (V.++) `eq` (++) 217 prop_concat :: P ([v a] -> v a) = V.concat `eq` concat 218 prop_force :: P (v a -> v a) = V.force `eq` id 219 prop_generate :: P (Int -> (Int -> a) -> v a) 220 = (\n _ -> n < 1000) ===> V.generate `eq` Util.generate 221 prop_generateM :: P (Int -> (Int -> Writer [a] a) -> Writer [a] (v a)) 222 = (\n _ -> n < 1000) ===> V.generateM `eq` Util.generateM 223 prop_iterateN :: P (Int -> (a -> a) -> a -> v a) 224 = (\n _ _ -> n < 1000) ===> V.iterateN `eq` (\n f -> take n . iterate f) 225 prop_iterateNM :: P (Int -> (a -> Writer [Int] a) -> a -> Writer [Int] (v a)) 226 = (\n _ _ -> n < 1000) ===> V.iterateNM `eq` Util.iterateNM 227 prop_create :: P (v a -> v a) 228 prop_create = (\v -> V.create (V.thaw v)) `eq` id 229 prop_createT :: P ((a, v a) -> (a, v a)) 230 prop_createT = (\v -> V.createT (T.mapM V.thaw v)) `eq` id 231 232 prop_head :: P (v a -> a) = not . V.null ===> V.head `eq` head 233 prop_last :: P (v a -> a) = not . V.null ===> V.last `eq` last 234 prop_index = \xs -> 235 not (V.null xs) ==> 236 forAll (choose (0, V.length xs-1)) $ \i -> 237 unP prop xs i 238 where 239 prop :: P (v a -> Int -> a) = (V.!) `eq` (!!) 240 prop_safeIndex :: P (v a -> Int -> Maybe a) = (V.!?) `eq` fn 241 where 242 fn xs i = case drop i xs of 243 x:_ | i >= 0 -> Just x 244 _ -> Nothing 245 prop_unsafeHead :: P (v a -> a) = not . V.null ===> V.unsafeHead `eq` head 246 prop_unsafeLast :: P (v a -> a) = not . V.null ===> V.unsafeLast `eq` last 247 prop_unsafeIndex = \xs -> 248 not (V.null xs) ==> 249 forAll (choose (0, V.length xs-1)) $ \i -> 250 unP prop xs i 251 where 252 prop :: P (v a -> Int -> a) = V.unsafeIndex `eq` (!!) 253 254 prop_slice = \xs -> 255 forAll (choose (0, V.length xs)) $ \i -> 256 forAll (choose (0, V.length xs - i)) $ \n -> 257 unP prop i n xs 258 where 259 prop :: P (Int -> Int -> v a -> v a) = V.slice `eq` slice 260 261 prop_tail :: P (v a -> v a) = not . V.null ===> V.tail `eq` tail 262 prop_init :: P (v a -> v a) = not . V.null ===> V.init `eq` init 263 prop_take :: P (Int -> v a -> v a) = V.take `eq` take 264 prop_drop :: P (Int -> v a -> v a) = V.drop `eq` drop 265 prop_splitAt :: P (Int -> v a -> (v a, v a)) = V.splitAt `eq` splitAt 266 267 prop_accum = \f xs -> 268 forAll (index_value_pairs (V.length xs)) $ \ps -> 269 unP prop f xs ps 270 where 271 prop :: P ((a -> a -> a) -> v a -> [(Int,a)] -> v a) 272 = V.accum `eq` accum 273 274 prop_upd = \xs -> 275 forAll (index_value_pairs (V.length xs)) $ \ps -> 276 unP prop xs ps 277 where 278 prop :: P (v a -> [(Int,a)] -> v a) = (V.//) `eq` (//) 279 280 prop_backpermute = \xs -> 281 forAll (indices (V.length xs)) $ \is -> 282 unP prop xs (V.fromList is) 283 where 284 prop :: P (v a -> v Int -> v a) = V.backpermute `eq` backpermute 285 286 prop_reverse :: P (v a -> v a) = V.reverse `eq` reverse 287 288 prop_map :: P ((a -> a) -> v a -> v a) = V.map `eq` map 289 prop_mapM :: P ((a -> Identity a) -> v a -> Identity (v a)) 290 = V.mapM `eq` mapM 291 prop_mapM_ :: P ((a -> Writer [a] ()) -> v a -> Writer [a] ()) 292 = V.mapM_ `eq` mapM_ 293 prop_forM :: P (v a -> (a -> Identity a) -> Identity (v a)) 294 = V.forM `eq` forM 295 prop_forM_ :: P (v a -> (a -> Writer [a] ()) -> Writer [a] ()) 296 = V.forM_ `eq` forM_ 297 prop_zipWith :: P ((a -> a -> a) -> v a -> v a -> v a) = V.zipWith `eq` zipWith 298 prop_zipWith3 :: P ((a -> a -> a -> a) -> v a -> v a -> v a -> v a) 299 = V.zipWith3 `eq` zipWith3 300 prop_imap :: P ((Int -> a -> a) -> v a -> v a) = V.imap `eq` imap 301 prop_imapM :: P ((Int -> a -> Identity a) -> v a -> Identity (v a)) 302 = V.imapM `eq` imapM 303 prop_imapM_ :: P ((Int -> a -> Writer [a] ()) -> v a -> Writer [a] ()) 304 = V.imapM_ `eq` imapM_ 305 prop_izipWith :: P ((Int -> a -> a -> a) -> v a -> v a -> v a) = V.izipWith `eq` izipWith 306 prop_zipWithM :: P ((a -> a -> Identity a) -> v a -> v a -> Identity (v a)) 307 = V.zipWithM `eq` zipWithM 308 prop_zipWithM_ :: P ((a -> a -> Writer [a] ()) -> v a -> v a -> Writer [a] ()) 309 = V.zipWithM_ `eq` zipWithM_ 310 prop_izipWithM :: P ((Int -> a -> a -> Identity a) -> v a -> v a -> Identity (v a)) 311 = V.izipWithM `eq` izipWithM 312 prop_izipWithM_ :: P ((Int -> a -> a -> Writer [a] ()) -> v a -> v a -> Writer [a] ()) 313 = V.izipWithM_ `eq` izipWithM_ 314 prop_izipWith3 :: P ((Int -> a -> a -> a -> a) -> v a -> v a -> v a -> v a) 315 = V.izipWith3 `eq` izipWith3 316 317 prop_filter :: P ((a -> Bool) -> v a -> v a) = V.filter `eq` filter 318 prop_ifilter :: P ((Int -> a -> Bool) -> v a -> v a) = V.ifilter `eq` ifilter 319 prop_filterM :: P ((a -> Writer [a] Bool) -> v a -> Writer [a] (v a)) = V.filterM `eq` filterM 320 prop_mapMaybe :: P ((a -> Maybe a) -> v a -> v a) = V.mapMaybe `eq` mapMaybe 321 prop_imapMaybe :: P ((Int -> a -> Maybe a) -> v a -> v a) = V.imapMaybe `eq` imapMaybe 322 prop_takeWhile :: P ((a -> Bool) -> v a -> v a) = V.takeWhile `eq` takeWhile 323 prop_dropWhile :: P ((a -> Bool) -> v a -> v a) = V.dropWhile `eq` dropWhile 324 prop_partition :: P ((a -> Bool) -> v a -> (v a, v a)) 325 = V.partition `eq` partition 326 prop_partitionWith :: P ((a -> Either a a) -> v a -> (v a, v a)) 327 = V.partitionWith `eq` partitionWith 328 prop_span :: P ((a -> Bool) -> v a -> (v a, v a)) = V.span `eq` span 329 prop_break :: P ((a -> Bool) -> v a -> (v a, v a)) = V.break `eq` break 330 331 prop_elem :: P (a -> v a -> Bool) = V.elem `eq` elem 332 prop_notElem :: P (a -> v a -> Bool) = V.notElem `eq` notElem 333 prop_find :: P ((a -> Bool) -> v a -> Maybe a) = V.find `eq` find 334 prop_findIndex :: P ((a -> Bool) -> v a -> Maybe Int) 335 = V.findIndex `eq` findIndex 336 prop_findIndexR :: P ((a -> Bool) -> v a -> Maybe Int) 337 = V.findIndexR `eq` \p l -> case filter (p . snd) . reverse $ zip [0..] l of 338 (i,_):_ -> Just i 339 [] -> Nothing 340 prop_findIndices :: P ((a -> Bool) -> v a -> v Int) 341 = V.findIndices `eq` findIndices 342 prop_elemIndex :: P (a -> v a -> Maybe Int) = V.elemIndex `eq` elemIndex 343 prop_elemIndices :: P (a -> v a -> v Int) = V.elemIndices `eq` elemIndices 344 345 prop_foldl :: P ((a -> a -> a) -> a -> v a -> a) = V.foldl `eq` foldl 346 prop_foldl1 :: P ((a -> a -> a) -> v a -> a) = notNull2 ===> 347 V.foldl1 `eq` foldl1 348 prop_foldl' :: P ((a -> a -> a) -> a -> v a -> a) = V.foldl' `eq` foldl' 349 prop_foldl1' :: P ((a -> a -> a) -> v a -> a) = notNull2 ===> 350 V.foldl1' `eq` foldl1' 351 prop_foldr :: P ((a -> a -> a) -> a -> v a -> a) = V.foldr `eq` foldr 352 prop_foldr1 :: P ((a -> a -> a) -> v a -> a) = notNull2 ===> 353 V.foldr1 `eq` foldr1 354 prop_foldr' :: P ((a -> a -> a) -> a -> v a -> a) = V.foldr' `eq` foldr 355 prop_foldr1' :: P ((a -> a -> a) -> v a -> a) = notNull2 ===> 356 V.foldr1' `eq` foldr1 357 prop_ifoldl :: P ((a -> Int -> a -> a) -> a -> v a -> a) 358 = V.ifoldl `eq` ifoldl 359 prop_ifoldl' :: P ((a -> Int -> a -> a) -> a -> v a -> a) 360 = V.ifoldl' `eq` ifoldl 361 prop_ifoldr :: P ((Int -> a -> a -> a) -> a -> v a -> a) 362 = V.ifoldr `eq` ifoldr 363 prop_ifoldr' :: P ((Int -> a -> a -> a) -> a -> v a -> a) 364 = V.ifoldr' `eq` ifoldr 365 prop_ifoldM :: P ((a -> Int -> a -> Identity a) -> a -> v a -> Identity a) 366 = V.ifoldM `eq` ifoldM 367 prop_ifoldM' :: P ((a -> Int -> a -> Identity a) -> a -> v a -> Identity a) 368 = V.ifoldM' `eq` ifoldM 369 prop_ifoldM_ :: P ((() -> Int -> a -> Writer [a] ()) -> () -> v a -> Writer [a] ()) 370 = V.ifoldM_ `eq` ifoldM_ 371 prop_ifoldM'_ :: P ((() -> Int -> a -> Writer [a] ()) -> () -> v a -> Writer [a] ()) 372 = V.ifoldM'_ `eq` ifoldM_ 373 374 prop_all :: P ((a -> Bool) -> v a -> Bool) = V.all `eq` all 375 prop_any :: P ((a -> Bool) -> v a -> Bool) = V.any `eq` any 376 377 prop_prescanl :: P ((a -> a -> a) -> a -> v a -> v a) 378 = V.prescanl `eq` prescanl 379 prop_prescanl' :: P ((a -> a -> a) -> a -> v a -> v a) 380 = V.prescanl' `eq` prescanl 381 prop_postscanl :: P ((a -> a -> a) -> a -> v a -> v a) 382 = V.postscanl `eq` postscanl 383 prop_postscanl' :: P ((a -> a -> a) -> a -> v a -> v a) 384 = V.postscanl' `eq` postscanl 385 prop_scanl :: P ((a -> a -> a) -> a -> v a -> v a) 386 = V.scanl `eq` scanl 387 prop_scanl' :: P ((a -> a -> a) -> a -> v a -> v a) 388 = V.scanl' `eq` scanl 389 prop_scanl1 :: P ((a -> a -> a) -> v a -> v a) = notNull2 ===> 390 V.scanl1 `eq` scanl1 391 prop_scanl1' :: P ((a -> a -> a) -> v a -> v a) = notNull2 ===> 392 V.scanl1' `eq` scanl1 393 prop_iscanl :: P ((Int -> a -> a -> a) -> a -> v a -> v a) 394 = V.iscanl `eq` iscanl 395 prop_iscanl' :: P ((Int -> a -> a -> a) -> a -> v a -> v a) 396 = V.iscanl' `eq` iscanl 397 398 prop_prescanr :: P ((a -> a -> a) -> a -> v a -> v a) 399 = V.prescanr `eq` prescanr 400 prop_prescanr' :: P ((a -> a -> a) -> a -> v a -> v a) 401 = V.prescanr' `eq` prescanr 402 prop_postscanr :: P ((a -> a -> a) -> a -> v a -> v a) 403 = V.postscanr `eq` postscanr 404 prop_postscanr' :: P ((a -> a -> a) -> a -> v a -> v a) 405 = V.postscanr' `eq` postscanr 406 prop_scanr :: P ((a -> a -> a) -> a -> v a -> v a) 407 = V.scanr `eq` scanr 408 prop_scanr' :: P ((a -> a -> a) -> a -> v a -> v a) 409 = V.scanr' `eq` scanr 410 prop_iscanr :: P ((Int -> a -> a -> a) -> a -> v a -> v a) 411 = V.iscanr `eq` iscanr 412 prop_iscanr' :: P ((Int -> a -> a -> a) -> a -> v a -> v a) 413 = V.iscanr' `eq` iscanr 414 prop_scanr1 :: P ((a -> a -> a) -> v a -> v a) = notNull2 ===> 415 V.scanr1 `eq` scanr1 416 prop_scanr1' :: P ((a -> a -> a) -> v a -> v a) = notNull2 ===> 417 V.scanr1' `eq` scanr1 418 419 prop_concatMap = forAll arbitrary $ \xs -> 420 forAll (sized (\n -> resize (n `div` V.length xs) arbitrary)) $ \f -> unP prop f xs 421 where 422 prop :: P ((a -> v a) -> v a -> v a) = V.concatMap `eq` concatMap 423 424 prop_uniq :: P (v a -> v a) 425 = V.uniq `eq` (map head . group) 426 427 -- Data.List 428 --prop_mapAccumL = eq3 429 -- (V.mapAccumL :: (X -> W -> (X,W)) -> X -> B -> (X, B)) 430 -- ( mapAccumL :: (X -> W -> (X,W)) -> X -> [W] -> (X, [W])) 431 -- 432 --prop_mapAccumR = eq3 433 -- (V.mapAccumR :: (X -> W -> (X,W)) -> X -> B -> (X, B)) 434 -- ( mapAccumR :: (X -> W -> (X,W)) -> X -> [W] -> (X, [W])) 435 436 -- Because the vectors are strict, we need to be totally sure that the unfold eventually terminates. This 437 -- is achieved by injecting our own bit of state into the unfold - the maximum number of unfolds allowed. 438 limitUnfolds f (theirs, ours) 439 | ours > 0 440 , Just (out, theirs') <- f theirs = Just (out, (theirs', ours - 1)) 441 | otherwise = Nothing 442 limitUnfoldsM f (theirs, ours) 443 | ours > 0 = do r <- f theirs 444 return $ (\(a,b) -> (a,(b,ours - 1))) `fmap` r 445 | otherwise = return Nothing 446 447 448 prop_unfoldr :: P (Int -> (Int -> Maybe (a,Int)) -> Int -> v a) 449 = (\n f a -> V.unfoldr (limitUnfolds f) (a, n)) 450 `eq` (\n f a -> unfoldr (limitUnfolds f) (a, n)) 451 prop_unfoldrN :: P (Int -> (Int -> Maybe (a,Int)) -> Int -> v a) 452 = V.unfoldrN `eq` (\n f a -> unfoldr (limitUnfolds f) (a, n)) 453 prop_unfoldrExactN :: P (Int -> (Int -> (a,Int)) -> Int -> v a) 454 = V.unfoldrExactN `eq` (\n f a -> unfoldr (limitUnfolds (Just . f)) (a, n)) 455 prop_unfoldrM :: P (Int -> (Int -> Writer [Int] (Maybe (a,Int))) -> Int -> Writer [Int] (v a)) 456 = (\n f a -> V.unfoldrM (limitUnfoldsM f) (a,n)) 457 `eq` (\n f a -> Util.unfoldrM (limitUnfoldsM f) (a, n)) 458 prop_unfoldrNM :: P (Int -> (Int -> Writer [Int] (Maybe (a,Int))) -> Int -> Writer [Int] (v a)) 459 = V.unfoldrNM `eq` (\n f a -> Util.unfoldrM (limitUnfoldsM f) (a, n)) 460 prop_unfoldrExactNM :: P (Int -> (Int -> Writer [Int] (a,Int)) -> Int -> Writer [Int] (v a)) 461 = V.unfoldrExactNM `eq` (\n f a -> Util.unfoldrM (limitUnfoldsM (liftM Just . f)) (a, n)) 462 463 prop_constructN = \f -> forAll (choose (0,20)) $ \n -> unP prop n f 464 where 465 prop :: P (Int -> (v a -> a) -> v a) = V.constructN `eq` constructN [] 466 467 constructN xs 0 _ = xs 468 constructN xs n f = constructN (xs ++ [f xs]) (n-1) f 469 470 prop_constructrN = \f -> forAll (choose (0,20)) $ \n -> unP prop n f 471 where 472 prop :: P (Int -> (v a -> a) -> v a) = V.constructrN `eq` constructrN [] 473 474 constructrN xs 0 _ = xs 475 constructrN xs n f = constructrN (f xs : xs) (n-1) f 476 477-- copied from GHC source code 478partitionWith :: (a -> Either b c) -> [a] -> ([b], [c]) 479partitionWith _ [] = ([],[]) 480partitionWith f (x:xs) = case f x of 481 Left b -> (b:bs, cs) 482 Right c -> (bs, c:cs) 483 where (bs,cs) = partitionWith f xs 484 485testTuplyFunctions 486 :: forall a v. ( CommonContext a v 487 , VectorContext (a, a) v 488 , VectorContext (a, a, a) v 489 , VectorContext (Int, a) v 490 ) 491 => v a -> [Test] 492{-# INLINE testTuplyFunctions #-} 493testTuplyFunctions _ = $(testProperties [ 'prop_zip, 'prop_zip3 494 , 'prop_unzip, 'prop_unzip3 495 , 'prop_indexed 496 , 'prop_update 497 ]) 498 where 499 prop_zip :: P (v a -> v a -> v (a, a)) = V.zip `eq` zip 500 prop_zip3 :: P (v a -> v a -> v a -> v (a, a, a)) = V.zip3 `eq` zip3 501 prop_unzip :: P (v (a, a) -> (v a, v a)) = V.unzip `eq` unzip 502 prop_unzip3 :: P (v (a, a, a) -> (v a, v a, v a)) = V.unzip3 `eq` unzip3 503 prop_indexed :: P (v a -> v (Int, a)) = V.indexed `eq` (\xs -> [0..] `zip` xs) 504 prop_update = \xs -> 505 forAll (index_value_pairs (V.length xs)) $ \ps -> 506 unP prop xs ps 507 where 508 prop :: P (v a -> [(Int,a)] -> v a) = (V.//) `eq` (//) 509 510testOrdFunctions :: forall a v. (CommonContext a v, Ord a, Ord (v a)) => v a -> [Test] 511{-# INLINE testOrdFunctions #-} 512testOrdFunctions _ = $(testProperties 513 ['prop_compare, 514 'prop_maximum, 'prop_minimum, 515 'prop_minIndex, 'prop_maxIndex, 516 'prop_maximumBy, 'prop_minimumBy, 517 'prop_maxIndexBy, 'prop_minIndexBy, 518 'prop_ListLastMaxIndexWins, 'prop_FalseListFirstMaxIndexWins ]) 519 where 520 prop_compare :: P (v a -> v a -> Ordering) = compare `eq` compare 521 prop_maximum :: P (v a -> a) = not . V.null ===> V.maximum `eq` maximum 522 prop_minimum :: P (v a -> a) = not . V.null ===> V.minimum `eq` minimum 523 prop_minIndex :: P (v a -> Int) = not . V.null ===> V.minIndex `eq` minIndex 524 prop_maxIndex :: P (v a -> Int) = not . V.null ===> V.maxIndex `eq` listMaxIndexFMW 525 prop_maximumBy :: P (v a -> a) = 526 not . V.null ===> V.maximumBy compare `eq` maximum 527 prop_minimumBy :: P (v a -> a) = 528 not . V.null ===> V.minimumBy compare `eq` minimum 529 prop_maxIndexBy :: P (v a -> Int) = 530 not . V.null ===> V.maxIndexBy compare `eq` listMaxIndexFMW 531 --- (maxIndex) 532 prop_ListLastMaxIndexWins :: P (v a -> Int) = 533 not . V.null ===> ( maxIndex . V.toList) `eq` listMaxIndexLMW 534 prop_FalseListFirstMaxIndexWinsDesc :: P (v a -> Int) = 535 (\x -> not $ V.null x && (V.uniq x /= x ) )===> ( maxIndex . V.toList) `eq` listMaxIndexFMW 536 prop_FalseListFirstMaxIndexWins :: Property 537 prop_FalseListFirstMaxIndexWins = expectFailure prop_FalseListFirstMaxIndexWinsDesc 538 prop_minIndexBy :: P (v a -> Int) = 539 not . V.null ===> V.minIndexBy compare `eq` minIndex 540 541listMaxIndexFMW :: Ord a => [a] -> Int 542listMaxIndexFMW = ( fst . extractFMW . sconcat . DLE.fromList . fmap FMW . zip [0 :: Int ..]) 543 544listMaxIndexLMW :: Ord a => [a] -> Int 545listMaxIndexLMW = ( fst . extractLMW . sconcat . DLE.fromList . fmap LMW . zip [0 :: Int ..]) 546 547newtype LastMaxWith a i = LMW {extractLMW:: (i,a)} 548 deriving(Eq,Show,Read) 549instance (Ord a) => Semigroup (LastMaxWith a i) where 550 (<>) x y | snd (extractLMW x) > snd (extractLMW y) = x 551 | snd (extractLMW x) < snd (extractLMW y) = y 552 | otherwise = y 553newtype FirstMaxWith a i = FMW {extractFMW:: (i,a)} 554 deriving(Eq,Show,Read) 555instance (Ord a) => Semigroup (FirstMaxWith a i) where 556 (<>) x y | snd (extractFMW x) > snd (extractFMW y) = x 557 | snd (extractFMW x) < snd (extractFMW y) = y 558 | otherwise = x 559 560 561testEnumFunctions :: forall a v. (CommonContext a v, Enum a, Ord a, Num a, Random a) => v a -> [Test] 562{-# INLINE testEnumFunctions #-} 563testEnumFunctions _ = $(testProperties 564 [ 'prop_enumFromN, 'prop_enumFromThenN, 565 'prop_enumFromTo, 'prop_enumFromThenTo]) 566 where 567 prop_enumFromN :: P (a -> Int -> v a) 568 = (\_ n -> n < 1000) 569 ===> V.enumFromN `eq` (\x n -> take n $ scanl (+) x $ repeat 1) 570 571 prop_enumFromThenN :: P (a -> a -> Int -> v a) 572 = (\_ _ n -> n < 1000) 573 ===> V.enumFromStepN `eq` (\x y n -> take n $ scanl (+) x $ repeat y) 574 575 prop_enumFromTo = \m -> 576 forAll (choose (-2,100)) $ \n -> 577 unP prop m (m+n) 578 where 579 prop :: P (a -> a -> v a) = V.enumFromTo `eq` enumFromTo 580 581 prop_enumFromThenTo = \i j -> 582 j /= i ==> 583 forAll (choose (ks i j)) $ \k -> 584 unP prop i j k 585 where 586 prop :: P (a -> a -> a -> v a) = V.enumFromThenTo `eq` enumFromThenTo 587 588 ks i j | j < i = (i-d*100, i+d*2) 589 | otherwise = (i-d*2, i+d*100) 590 where 591 d = abs (j-i) 592 593testMonoidFunctions :: forall a v. (CommonContext a v, Monoid (v a)) => v a -> [Test] 594{-# INLINE testMonoidFunctions #-} 595testMonoidFunctions _ = $(testProperties 596 [ 'prop_mempty, 'prop_mappend, 'prop_mconcat ]) 597 where 598 prop_mempty :: P (v a) = mempty `eq` mempty 599 prop_mappend :: P (v a -> v a -> v a) = mappend `eq` mappend 600 prop_mconcat :: P ([v a] -> v a) = mconcat `eq` mconcat 601 602testFunctorFunctions :: forall a v. (CommonContext a v, Functor v) => v a -> [Test] 603{-# INLINE testFunctorFunctions #-} 604testFunctorFunctions _ = $(testProperties 605 [ 'prop_fmap ]) 606 where 607 prop_fmap :: P ((a -> a) -> v a -> v a) = fmap `eq` fmap 608 609testMonadFunctions :: forall a v. (CommonContext a v, VectorContext (a, a) v, MonadZip v) => v a -> [Test] 610{-# INLINE testMonadFunctions #-} 611testMonadFunctions _ = $(testProperties [ 'prop_return, 'prop_bind 612 , 'prop_mzip, 'prop_munzip 613 ]) 614 where 615 prop_return :: P (a -> v a) = return `eq` return 616 prop_bind :: P (v a -> (a -> v a) -> v a) = (>>=) `eq` (>>=) 617 prop_mzip :: P (v a -> v a -> v (a, a)) = mzip `eq` zip 618 prop_munzip :: P (v (a, a) -> (v a, v a)) = munzip `eq` unzip 619 620testSequenceFunctions 621 :: forall a v. ( CommonContext a v 622 , Model (v (Writer [a] a)) ~ [Writer [a] a] 623 , V.Vector v (Writer [a] a) 624 , Arbitrary (v (Writer [a] a)) 625 , Show (v (Writer [a] a)) 626 , TestData (v (Writer [a] a)) 627 ) 628 => v a -> [Test] 629testSequenceFunctions _ = $(testProperties [ 'prop_sequence, 'prop_sequence_ 630 ]) 631 where 632 prop_sequence :: P (v (Writer [a] a) -> Writer [a] (v a)) 633 = V.sequence `eq` sequence 634 prop_sequence_ :: P (v (Writer [a] a) -> Writer [a] ()) 635 = V.sequence_ `eq` sequence_ 636 637testApplicativeFunctions :: forall a v. (CommonContext a v, V.Vector v (a -> a), Applicative.Applicative v) => v a -> [Test] 638{-# INLINE testApplicativeFunctions #-} 639testApplicativeFunctions _ = $(testProperties 640 [ 'prop_applicative_pure, 'prop_applicative_appl ]) 641 where 642 prop_applicative_pure :: P (a -> v a) 643 = Applicative.pure `eq` Applicative.pure 644 prop_applicative_appl :: [a -> a] -> P (v a -> v a) 645 = \fs -> (Applicative.<*>) (V.fromList fs) `eq` (Applicative.<*>) fs 646 647testAlternativeFunctions :: forall a v. (CommonContext a v, Applicative.Alternative v) => v a -> [Test] 648{-# INLINE testAlternativeFunctions #-} 649testAlternativeFunctions _ = $(testProperties 650 [ 'prop_alternative_empty, 'prop_alternative_or ]) 651 where 652 prop_alternative_empty :: P (v a) = Applicative.empty `eq` Applicative.empty 653 prop_alternative_or :: P (v a -> v a -> v a) 654 = (Applicative.<|>) `eq` (Applicative.<|>) 655 656testBoolFunctions :: forall v. (CommonContext Bool v) => v Bool -> [Test] 657{-# INLINE testBoolFunctions #-} 658testBoolFunctions _ = $(testProperties ['prop_and, 'prop_or]) 659 where 660 prop_and :: P (v Bool -> Bool) = V.and `eq` and 661 prop_or :: P (v Bool -> Bool) = V.or `eq` or 662 663testNumFunctions :: forall a v. (CommonContext a v, Num a) => v a -> [Test] 664{-# INLINE testNumFunctions #-} 665testNumFunctions _ = $(testProperties ['prop_sum, 'prop_product]) 666 where 667 prop_sum :: P (v a -> a) = V.sum `eq` sum 668 prop_product :: P (v a -> a) = V.product `eq` product 669 670testNestedVectorFunctions :: forall a v. (CommonContext a v) => v a -> [Test] 671{-# INLINE testNestedVectorFunctions #-} 672testNestedVectorFunctions _ = $(testProperties 673 [ 'prop_concat 674 ]) 675 where 676 prop_concat :: P ([v a] -> v a) = V.concat `eq` concat 677 678testDataFunctions :: forall a v. (CommonContext a v, Data a, Data (v a)) => v a -> [Test] 679{-# INLINE testDataFunctions #-} 680testDataFunctions _ = $(testProperties ['prop_glength]) 681 where 682 prop_glength :: P (v a -> Int) = glength `eq` glength 683 where 684 glength :: Data b => b -> Int 685 glength xs = gmapQl (+) 0 toA xs 686 687 toA :: Data b => b -> Int 688 toA x = maybe (glength x) (const 1) (cast x :: Maybe a) 689