nonempty-vector-0.3: test/Test/Data/Vector/NonEmpty/Grouping.hs
module Test.Data.Vector.NonEmpty.Grouping
( tests
) where
import qualified Data.List as List
import qualified Data.List.NonEmpty as NonEmpty
import Data.Vector.NonEmpty (NonEmptyVector)
import qualified Data.Vector.NonEmpty as NEV
import Test.Data.Vector.NonEmpty.Util
import Test.QuickCheck
import Test.Tasty
import Test.Tasty.QuickCheck
tests :: TestTree
tests = testGroup "Grouping"
[ testGroup "group"
[ testProperty "prop_group" prop_group
, testProperty "prop_group_singleton" prop_group_singleton
, testProperty "prop_group_all_equal" prop_group_all_equal
, testProperty "prop_group_distinct" prop_group_distinct
, testProperty "prop_group_runs" prop_group_runs
]
, testGroup "groupBy"
[ testProperty "prop_groupBy" prop_groupBy
, testProperty "prop_groupBy_singleton" prop_groupBy_singleton
, testProperty "prop_groupBy_all_true" prop_groupBy_all_true
, testProperty "prop_groupBy_all_false" prop_groupBy_all_false
, testProperty "prop_groupBy_equivalence" prop_groupBy_equivalence
, testProperty "prop_groupBy_nontransitive" prop_groupBy_nontransitive
, testProperty "prop_groupBy_asymmetric" prop_groupBy_asymmetric
]
]
groupElems :: NonEmpty.NonEmpty (NonEmptyVector element) -> [[element]]
groupElems = List.map elems . NonEmpty.toList
prop_group :: NonEmptyVector Int -> Property
prop_group input =
groupElems (NEV.group (vec values)) === List.group values
where
values = List.map (`mod` 4) (elems input)
prop_group_singleton :: Int -> Property
prop_group_singleton value =
groupElems (NEV.group (vec [value])) === [[value]]
prop_group_all_equal :: Int -> Positive Int -> Property
prop_group_all_equal value (Positive count) =
groupElems (NEV.group (vec values)) === [values]
where
values = List.replicate count value
prop_group_distinct :: NonEmptyVector Int -> Property
prop_group_distinct input =
groupElems (NEV.group (vec values)) === List.map (: []) values
where
values = List.nub (elems input)
prop_group_runs :: Property
prop_group_runs = once $
groupElems (NEV.group (vec "Mississippi"))
=== ["M", "i", "ss", "i", "ss", "i", "pp", "i"]
prop_groupBy :: Fun (Int, Int) Bool -> NonEmptyVector Int -> Property
prop_groupBy (Fn2 predicate) input =
groupElems (NEV.groupBy predicate (vec values))
=== List.groupBy predicate values
where
values = List.map (`mod` 4) (elems input)
prop_groupBy_singleton :: Int -> Property
prop_groupBy_singleton value =
groupElems (NEV.groupBy predicate (vec [value])) === [[value]]
where
predicate _ _ = error "groupBy evaluated its predicate on a singleton"
prop_groupBy_all_true :: NonEmptyVector Int -> Property
prop_groupBy_all_true input =
groupElems (NEV.groupBy (\_ _ -> True) input) === [elems input]
prop_groupBy_all_false :: NonEmptyVector Int -> Property
prop_groupBy_all_false input =
groupElems (NEV.groupBy (\_ _ -> False) input)
=== List.map (: []) (elems input)
prop_groupBy_equivalence :: NonEmptyVector Int -> Property
prop_groupBy_equivalence input =
groupElems (NEV.groupBy sameParity input)
=== List.groupBy sameParity (elems input)
where
sameParity first second = even first == even second
prop_groupBy_nontransitive :: Property
prop_groupBy_nontransitive = once $
groupElems (NEV.groupBy nearby (vec [1, 2, 3, 4] :: NonEmptyVector Int))
=== [[1, 2], [3, 4]]
where
nearby first second = abs (first - second) <= 1
prop_groupBy_asymmetric :: Property
prop_groupBy_asymmetric = once $
groupElems (NEV.groupBy (<) (vec [1, 2, 1, 3, 0, 4] :: NonEmptyVector Int))
=== [[1, 2], [1, 3], [0, 4]]