Skip to content

Commit b4ea836

Browse files
committed
Test and benchmark fromAscList and friends
Add property tests and benchmarks for fromAscList and related functions for Set and Map.
1 parent e3bd02d commit b4ea836

File tree

4 files changed

+118
-47
lines changed

4 files changed

+118
-47
lines changed

containers-tests/benchmarks/Map.hs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ main = do
2121
m_even = M.fromAscList elems_even :: M.Map Int Int
2222
m_odd = M.fromAscList elems_odd :: M.Map Int Int
2323
evaluate $ rnf [m, m_even, m_odd]
24-
evaluate $ rnf elems_rev
24+
evaluate $ rnf [elems_rev, elems_asc, elems_desc]
2525
defaultMain
2626
[ bench "lookup absent" $ whnf (lookup evens) m_odd
2727
, bench "lookup present" $ whnf (lookup evens) m_even
@@ -71,7 +71,7 @@ main = do
7171
, bench "insertLookupWithKey' present" $ whnf (insLookupWithKey' elems_even) m_even
7272
, bench "mapWithKey" $ whnf (M.mapWithKey (+)) m
7373
, bench "foldlWithKey" $ whnf (ins elems) m
74-
, bench "foldlWithKey'" $ whnf (M.foldlWithKey' sum 0) m
74+
, bench "foldlWithKey'" $ whnf (M.foldlWithKey' sumkv 0) m
7575
, bench "foldrWithKey" $ whnf (M.foldrWithKey consPair []) m
7676
, bench "foldrWithKey'" $ whnf (M.foldrWithKey' consPair []) m
7777
, bench "update absent" $ whnf (upd Just evens) m_odd
@@ -88,8 +88,13 @@ main = do
8888
, bench "intersection" $ whnf (M.intersection m) m_even
8989
, bench "split" $ whnf (M.split (bound `div` 2)) m
9090
, bench "fromList" $ whnf M.fromList elems
91-
, bench "fromList-desc" $ whnf M.fromList (reverse elems)
92-
, bench "fromAscList" $ whnf M.fromAscList elems
91+
, bench "fromList-desc" $ whnf M.fromList elems_desc
92+
, bench "fromAscList" $ whnf M.fromAscList elems_asc
93+
, bench "fromAscListWithKey" $
94+
whnf (M.fromAscListWithKey sumkv) elems_asc
95+
, bench "fromDescList" $ whnf M.fromDescList elems_desc
96+
, bench "fromDescListWithKey" $
97+
whnf (M.fromDescListWithKey sumkv) elems_desc
9398
, bench "fromDistinctAscList" $ whnf M.fromDistinctAscList elems
9499
, bench "fromDistinctAscList:fusion" $ whnf (\n -> M.fromDistinctAscList [(i,i) | i <- [1..n]]) bound
95100
, bench "fromDistinctDescList" $ whnf M.fromDistinctDescList elems_rev
@@ -104,11 +109,15 @@ main = do
104109
elems_even = zip evens evens
105110
elems_odd = zip odds odds
106111
elems_rev = reverse elems
112+
keys_asc = map (`div` 2) [1..bound] -- [0,1,1,2,2..]
113+
elems_asc = zip keys_asc values
114+
keys_desc = map (`div` 2) [bound,bound-1..1] -- [..2,2,1,1,0]
115+
elems_desc = zip keys_desc values
107116
keys = [1..bound]
108117
evens = [2,4..bound]
109118
odds = [1,3..bound]
110119
values = [1..bound]
111-
sum k v1 v2 = k + v1 + v2
120+
sumkv k v1 v2 = k + v1 + v2
112121
consPair k v xs = (k, v) : xs
113122

114123
add3 :: Int -> Int -> Int -> Int

containers-tests/benchmarks/Set.hs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ main = do
1414
s_odd = S.fromAscList elems_odd :: S.Set Int
1515
strings_s = S.fromList strings
1616
evaluate $ rnf [s, s_even, s_odd]
17-
evaluate $ rnf elems_rev
17+
evaluate $ rnf [elems_rev, elems_asc, elems_desc]
1818
defaultMain
1919
[ bench "member" $ whnf (member elems) s
2020
, bench "insert" $ whnf (ins elems) S.empty
@@ -33,9 +33,10 @@ main = do
3333
, bench "intersection" $ whnf (S.intersection s) s_even
3434
, bench "fromList" $ whnf S.fromList elems
3535
, bench "fromList-desc" $ whnf S.fromList (reverse elems)
36-
, bench "fromAscList" $ whnf S.fromAscList elems
36+
, bench "fromAscList" $ whnf S.fromAscList elems_asc
3737
, bench "fromDistinctAscList" $ whnf S.fromDistinctAscList elems
3838
, bench "fromDistinctAscList:fusion" $ whnf (\n -> S.fromDistinctAscList [1..n]) bound
39+
, bench "fromDescList" $ whnf S.fromDescList elems_desc
3940
, bench "fromDistinctDescList" $ whnf S.fromDistinctDescList elems_rev
4041
, bench "fromDistinctDescList:fusion" $ whnf (\n -> S.fromDistinctDescList [n,n-1..1]) bound
4142
, bench "disjoint:false" $ whnf (S.disjoint s) s_even
@@ -64,6 +65,8 @@ main = do
6465
elems_even = [2,4..bound]
6566
elems_odd = [1,3..bound]
6667
elems_rev = reverse elems
68+
elems_asc = map (`div` 2) [1..bound] -- [0,1,1,2,2..]
69+
elems_desc = map (`div` 2) [bound,bound-1..1] -- [..2,2,1,1,0]
6770
strings = map show elems
6871

6972
member :: [Int] -> S.Set Int -> Int

containers-tests/tests/map-properties.hs

Lines changed: 70 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import qualified Prelude
2828

2929
import Data.List (nub,sort)
3030
import qualified Data.List as List
31+
import Data.List.NonEmpty (NonEmpty(..))
32+
import qualified Data.List.NonEmpty as NE
3133
import qualified Data.Set as Set
3234
import Test.Tasty
3335
import Test.Tasty.HUnit
@@ -185,9 +187,13 @@ main = defaultMain $ testGroup "map-properties"
185187
, testProperty "unionWithKeyMerge" prop_unionWithKeyMerge
186188
, testProperty "mergeWithKey model" prop_mergeWithKeyModel
187189
, testProperty "mergeA effects" prop_mergeA_effects
188-
, testProperty "fromAscList" prop_ordered
190+
, testProperty "fromAscList" prop_fromAscList
191+
, testProperty "fromAscListWith" prop_fromAscListWith
192+
, testProperty "fromAscListWithKey" prop_fromAscListWithKey
189193
, testProperty "fromDistinctAscList" prop_fromDistinctAscList
190-
, testProperty "fromDescList" prop_rev_ordered
194+
, testProperty "fromDescList" prop_fromDescList
195+
, testProperty "fromDescListWith" prop_fromDescListWith
196+
, testProperty "fromDescListWithKey" prop_fromDescListWithKey
191197
, testProperty "fromDistinctDescList" prop_fromDistinctDescList
192198
, testProperty "fromList then toList" prop_list
193199
, testProperty "toDescList" prop_descList
@@ -1272,31 +1278,46 @@ instance Arbitrary WhenMatchedSpec where
12721278

12731279
----------------------------------------------------------------
12741280

1275-
prop_ordered :: Property
1276-
prop_ordered
1277-
= forAll (choose (5,100)) $ \n ->
1278-
let xs = [(x,()) | x <- [0..n::Int]]
1279-
in fromAscList xs == fromList xs
1280-
1281-
prop_rev_ordered :: Property
1282-
prop_rev_ordered
1283-
= forAll (choose (5,100)) $ \n ->
1284-
let xs = [(x,()) | x <- [0..n::Int]]
1285-
in fromDescList (reverse xs) == fromList xs
1286-
12871281
prop_list :: [Int] -> Bool
12881282
prop_list xs = (sort (nub xs) == [x | (x,()) <- toList (fromList [(x,()) | x <- xs])])
12891283

12901284
prop_descList :: [Int] -> Bool
12911285
prop_descList xs = (reverse (sort (nub xs)) == [x | (x,()) <- toDescList (fromList [(x,()) | x <- xs])])
12921286

1287+
prop_fromDescList :: [(Int, A)] -> Property
1288+
prop_fromDescList kxs =
1289+
valid t .&&.
1290+
t === fromList kxs
1291+
where
1292+
downSortedKxs = List.sortBy (comparing (Down . fst)) kxs
1293+
t = fromDescList downSortedKxs
1294+
1295+
prop_fromDescListWith :: Fun (A, A) A -> [(Int, A)] -> Property
1296+
prop_fromDescListWith f kxs =
1297+
valid t .&&.
1298+
t === fromListWith (apply2 f) downSortedKxs
1299+
where
1300+
downSortedKxs = List.sortBy (comparing (Down . fst)) kxs
1301+
t = fromDescListWith (apply2 f) downSortedKxs
1302+
1303+
prop_fromDescListWithKey :: Fun (Int, A, A) A -> [(Int, A)] -> Property
1304+
prop_fromDescListWithKey f kxs =
1305+
valid t .&&.
1306+
t === fromListWithKey (apply3 f) downSortedKxs
1307+
where
1308+
downSortedKxs = List.sortBy (comparing (Down . fst)) kxs
1309+
t = fromDescListWithKey (apply3 f) downSortedKxs
1310+
12931311
prop_fromDistinctDescList :: [(Int, A)] -> Property
1294-
prop_fromDistinctDescList xs =
1312+
prop_fromDistinctDescList kxs =
12951313
valid t .&&.
1296-
toList t === nub_sort_xs
1314+
toList t === reverse nubDownSortedKxs
12971315
where
1298-
t = fromDistinctDescList (reverse nub_sort_xs)
1299-
nub_sort_xs = List.map List.head $ List.groupBy ((==) `on` fst) $ List.sortBy (comparing fst) xs
1316+
nubDownSortedKxs =
1317+
List.map NE.head $
1318+
NE.groupBy ((==) `on` fst) $
1319+
List.sortBy (comparing (Down . fst)) kxs
1320+
t = fromDistinctDescList nubDownSortedKxs
13001321

13011322
prop_ascDescList :: [Int] -> Bool
13021323
prop_ascDescList xs = toAscList m == reverse (toDescList m)
@@ -1309,13 +1330,40 @@ prop_fromList xs
13091330
t == List.foldr (uncurry insert) empty (zip xs xs)
13101331
where sort_xs = sort xs
13111332

1333+
prop_fromAscList :: [(Int, A)] -> Property
1334+
prop_fromAscList kxs =
1335+
valid t .&&.
1336+
t === fromList sortedKxs
1337+
where
1338+
sortedKxs = List.sortBy (comparing fst) kxs
1339+
t = fromAscList sortedKxs
1340+
1341+
prop_fromAscListWith :: Fun (A, A) A -> [(Int, A)] -> Property
1342+
prop_fromAscListWith f kxs =
1343+
valid t .&&.
1344+
t === fromListWith (apply2 f) sortedKxs
1345+
where
1346+
sortedKxs = List.sortBy (comparing fst) kxs
1347+
t = fromAscListWith (apply2 f) sortedKxs
1348+
1349+
prop_fromAscListWithKey :: Fun (Int, A, A) A -> [(Int, A)] -> Property
1350+
prop_fromAscListWithKey f kxs =
1351+
valid t .&&.
1352+
t === fromListWithKey (apply3 f) sortedKxs
1353+
where
1354+
sortedKxs = List.sortBy (comparing fst) kxs
1355+
t = fromAscListWithKey (apply3 f) sortedKxs
1356+
13121357
prop_fromDistinctAscList :: [(Int, A)] -> Property
1313-
prop_fromDistinctAscList xs =
1358+
prop_fromDistinctAscList kxs =
13141359
valid t .&&.
1315-
toList t === nub_sort_xs
1360+
toList t === nubSortedKxs
13161361
where
1317-
t = fromDistinctAscList nub_sort_xs
1318-
nub_sort_xs = List.map List.head $ List.groupBy ((==) `on` fst) $ List.sortBy (comparing fst) xs
1362+
nubSortedKxs =
1363+
List.map NE.head $
1364+
NE.groupBy ((==) `on` fst) $
1365+
List.sortBy (comparing fst) kxs
1366+
t = fromDistinctAscList nubSortedKxs
13191367

13201368
----------------------------------------------------------------
13211369

containers-tests/tests/set-properties.hs

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{-# LANGUAGE CPP #-}
22
import qualified Data.IntSet as IntSet
3-
import Data.List (nub,sort)
3+
import Data.List (nub, sort, sortBy)
44
import qualified Data.List as List
55
import Data.Monoid (mempty)
66
import Data.Maybe
@@ -15,7 +15,9 @@ import Control.Monad.Trans.Class
1515
import Control.Monad (liftM, liftM3)
1616
import Data.Functor.Identity
1717
import Data.Foldable (all)
18+
import Data.Ord (Down(..), comparing)
1819
import Control.Applicative (liftA2)
20+
import qualified Data.List.NonEmpty as NE
1921

2022
#if __GLASGOW_HASKELL__ >= 806
2123
import Utils.NoThunks (whnfHasNoThunks)
@@ -67,8 +69,9 @@ main = defaultMain $ testGroup "set-properties"
6769
, testProperty "prop_DescList" prop_DescList
6870
, testProperty "prop_AscDescList" prop_AscDescList
6971
, testProperty "prop_fromList" prop_fromList
72+
, testProperty "prop_fromAscList" prop_fromAscList
7073
, testProperty "prop_fromDistinctAscList" prop_fromDistinctAscList
71-
, testProperty "prop_fromListDesc" prop_fromListDesc
74+
, testProperty "prop_fromDescList" prop_fromDescList
7275
, testProperty "prop_fromDistinctDescList" prop_fromDistinctDescList
7376
, testProperty "prop_isProperSubsetOf" prop_isProperSubsetOf
7477
, testProperty "prop_isProperSubsetOf2" prop_isProperSubsetOf2
@@ -528,35 +531,43 @@ prop_AscDescList xs = toAscList s == reverse (toDescList s)
528531

529532
prop_fromList :: [Int] -> Property
530533
prop_fromList xs =
531-
t === fromAscList sort_xs .&&.
534+
valid t .&&.
532535
t === List.foldr insert empty xs
533536
where t = fromList xs
534-
sort_xs = sort xs
537+
538+
prop_fromAscList :: [Int] -> Property
539+
prop_fromAscList xs =
540+
valid t .&&.
541+
toList t === nubSortedXs
542+
where
543+
sortedXs = sort xs
544+
nubSortedXs = List.map NE.head $ NE.group sortedXs
545+
t = fromAscList sortedXs
535546

536547
prop_fromDistinctAscList :: [Int] -> Property
537548
prop_fromDistinctAscList xs =
538549
valid t .&&.
539-
toList t === nub_sort_xs
550+
toList t === nubSortedXs
540551
where
541-
t = fromDistinctAscList nub_sort_xs
542-
nub_sort_xs = List.map List.head $ List.group $ sort xs
552+
nubSortedXs = List.map NE.head $ NE.group $ sort xs
553+
t = fromDistinctAscList nubSortedXs
543554

544-
prop_fromListDesc :: [Int] -> Property
545-
prop_fromListDesc xs =
546-
t === fromDescList sort_xs .&&.
547-
t === fromDistinctDescList nub_sort_xs .&&.
548-
t === List.foldr insert empty xs
549-
where t = fromList xs
550-
sort_xs = reverse (sort xs)
551-
nub_sort_xs = List.map List.head $ List.group sort_xs
555+
prop_fromDescList :: [Int] -> Property
556+
prop_fromDescList xs =
557+
valid t .&&.
558+
toList t === reverse nubDownSortedXs
559+
where
560+
downSortedXs = sortBy (comparing Down) xs
561+
nubDownSortedXs = List.map NE.head $ NE.group downSortedXs
562+
t = fromDescList downSortedXs
552563

553564
prop_fromDistinctDescList :: [Int] -> Property
554565
prop_fromDistinctDescList xs =
555566
valid t .&&.
556-
toList t === nub_sort_xs
567+
toList t === reverse nubDownSortedXs
557568
where
558-
t = fromDistinctDescList (reverse nub_sort_xs)
559-
nub_sort_xs = List.map List.head $ List.group $ sort xs
569+
nubDownSortedXs = List.map NE.head $ NE.group $ sortBy (comparing Down) xs
570+
t = fromDistinctDescList nubDownSortedXs
560571

561572
{--------------------------------------------------------------------
562573
Set operations are like IntSet operations

0 commit comments

Comments
 (0)