{-# LANGUAGE CPP, MultiParamTypeClasses, FlexibleInstances #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Properties.Set where import qualified Data.ByteString.Char8 as B import Data.CritBit.Map.Lazy (CritBitKey, byteCount) import qualified Data.CritBit.Set as C import Data.List (unfoldr, sort, nub) import qualified Data.Set as S import qualified Data.Text as T import Properties.Common import Test.Framework (Test, testGroup) import Test.Framework.Providers.QuickCheck2 (testProperty) import Test.QuickCheck.Property ((.&&.)) kp :: (CritBitKey k) => k -> Bool kp = even . byteCount kii :: (CritBitKey k, Show k) => k -> Int -> Int kii k v = byteCount k * 13 + v propertiesFor :: Props k propertiesFor t = concat [[] -- * Operators , prop "t_diff" $ (C.\\) =**= (S.\\) -- * Query , prop "t_null" $ C.null =*= S.null , prop "t_size" $ C.size =*= S.size , prop "t_member" $ C.member =?*= S.member , prop "t_notMember" $ C.notMember =?*= S.notMember #if MIN_VERSION_containers(0,5,0) , prop "t_lookupLT" $ C.lookupLT =?*= S.lookupLT , prop "t_lookupGT" $ C.lookupGT =?*= S.lookupGT , prop "t_lookupLE" $ C.lookupLE =?*= S.lookupLE , prop "t_lookupGE" $ C.lookupGE =?*= S.lookupGE #endif , prop "t_isSubsetOf" $ C.isSubsetOf =**= S.isSubsetOf , prop "t_isProperSubsetOf" $ C.isProperSubsetOf =**= S.isProperSubsetOf -- * Construction -- , prop "t_empty" $ C.empty =^= S.empty , prop "t_singleton" $ notEmpty $ (C.singleton =*== S.singleton) head , prop "t_insert" $ C.insert =?*= S.insert , prop "t_delete" $ C.delete =?*= S.delete -- * Combine , prop "t_union" $ C.union =**= S.union , prop "t_unions" $ (C.unions . map C.fromList =*== S.unions . map S.fromList) fromSmall , prop "t_difference" $ C.difference =**= S.difference , prop "t_intersection" $ C.intersection =**= S.intersection -- * Filter , prop "t_filter" $ C.filter kp =*= S.filter kp , prop "t_partition" $ C.partition kp =*= S.partition kp , prop "t_split" $ C.split =?*= S.split , prop "t_splitMember" $ C.splitMember =?*= S.splitMember -- * Map , prop "t_map" $ C.map kf =*= S.map kf , prop "t_mapMonotonic" $ C.mapMonotonic prepends =*= S.mapMonotonic prepends -- * Folds , prop "t_foldr" $ C.foldr kii 0 =*= S.foldr kii 0 , prop "t_foldl" $ C.foldl (flip kii) 0 =*= S.foldl (flip kii) 0 -- ** Strict folds , prop "t_foldr'" $ C.foldr' kii 0 =*= S.foldr' kii 0 , prop "t_foldl'" $ C.foldl' (flip kii) 0 =*= S.foldl' (flip kii) 0 -- * Min\/Max , prop "t_findMin" $ notEmpty $ C.findMin =*= S.findMin , prop "t_findMax" $ notEmpty $ C.findMax =*= S.findMax , prop "t_deleteMin" $ notEmpty $ C.deleteMin =*= S.deleteMin , prop "t_deleteMax" $ notEmpty $ C.deleteMax =*= S.deleteMax , prop "t_deleteFindMin" $ notEmpty $ C.deleteFindMin =*= S.deleteFindMin , prop "t_deleteFindMax" $ notEmpty $ C.deleteFindMax =*= S.deleteFindMax , prop "t_maxView" $ notEmpty $ unfoldr C.maxView =*= unfoldr S.maxView , prop "t_minView" $ notEmpty $ unfoldr C.minView =*= unfoldr S.minView -- * Conversion -- ** List , prop "t_elems" $ C.elems =*= S.elems , prop "t_toList" $ C.toList =*= S.toList , prop "t_fromList" $ (C.fromList =*== S.fromList) id -- ** Ordered list , prop "t_toAscList" $ C.toAscList =*= S.toAscList #if MIN_VERSION_containers(0,5,0) , prop "t_toDescList" $ C.toDescList =*= S.toDescList #endif , prop "t_fromAscList" $ (C.fromAscList =*== S.fromAscList) sort , prop "t_fromDistinctAscList" $ (C.fromDistinctAscList =*== S.fromDistinctAscList) (nub . sort) ] where prop name q = [testProperty name $ q $ sameAs t] sameAs :: (CritBitKey k, Ord k) => k -> SameAs (C.Set k) (S.Set k) [k] sameAs _ = SameAs C.fromList C.toList S.fromList S.toList properties :: [Test] properties = [ testGroup "text" $ propertiesFor T.empty , testGroup "bytestring" $ propertiesFor B.empty ] instance (Show k, Eq k) => Eq' (C.Set k) (S.Set k) where c =^= m = C.toList c =^= S.toList m instance (Eq' a1 b1, Eq k, Show k) => Eq' (a1, C.Set k) (b1, S.Set k) where (a1, a2) =^= (b1, b2) = a1 =^= b1 .&&. a2 =^= b2 -- Handy functions for fiddling with from ghci. blist :: [B.ByteString] -> C.Set B.ByteString blist = C.fromList tlist :: [T.Text] -> S.Set T.Text tlist = S.fromList