packages feed

bitset 0.6 → 1.0

raw patch · 5 files changed

+68/−86 lines, 5 filesdep ~basesetup-changedPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base

API changes (from Hackage documentation)

- Data.BitSet: class Hash a
- Data.BitSet: hash :: Hash a => a -> Int
- Data.BitSet: instance Hash Int
- Data.BitSet: instance Hash Integer
- Data.BitSet: instance Show (BitSet a)
+ Data.BitSet: fromList :: Enum a => [a] -> BitSet a
+ Data.BitSet: instance (Enum a, Show a) => Show (BitSet a)
+ Data.BitSet: instance Data a => Data (BitSet a)
+ Data.BitSet: instance Ord (BitSet a)
+ Data.BitSet: instance Typeable1 BitSet
- Data.BitSet: delete :: Hash a => a -> BitSet a -> BitSet a
+ Data.BitSet: delete :: Enum a => a -> BitSet a -> BitSet a
- Data.BitSet: insert :: Hash a => a -> BitSet a -> BitSet a
+ Data.BitSet: insert :: Enum a => a -> BitSet a -> BitSet a
- Data.BitSet: member :: Hash a => a -> BitSet a -> Bool
+ Data.BitSet: member :: Enum a => a -> BitSet a -> Bool

Files

Data/BitSet.hs view
@@ -1,14 +1,13 @@ -- | A /bit set/ maintains a record of members from a type that can be mapped--- into (non-negative) @Int@s.  Supports insertion, deletion, size, and+-- into (non-negative) @Int@s. The maximum number of elements that can be+-- stored is @maxbound :: Int@. Supports insertion, deletion, size, and -- membership testing, and is completely pure (functional). ----- To use this library, simply supply a `Hash' instance for your data type.--- (See the `Hash' class for the relevant laws your instance must obey.)  Each--- operation requires at most one call to `hash'.  It is important that the--- values you intend to keep track of start from 0 and go up.  A value which--- `hash'es to @n@ corresponds to bit location @n@ in an @Integer@, and thus--- requires that @Integer@ to have at least @n@ bits.  Don't shoot yourself in--- the foot by `hash'ing to big @Int@s.+-- To use this library, simply supply a `Enum' instance for your data type or+-- have it derived. It is important that the values you intend to keep track+-- of start from 0 and go up. A value for which @fromEnum x@ is @n@+-- corresponds to bit location @n@ in an @Integer@, and thus requires that+-- @Integer@ to have at least @n@ bits. -- -- The implementation is quite simple: we rely on the @Bits Integer@ instance -- from @Data.Bits@.  An advantage of this library over simply using that@@ -16,11 +15,11 @@ -- The interface we expose ensures client code will not typecheck if it -- confuses two bit sets intended to keep track of different types. module Data.BitSet-    ( Hash(..)-    , BitSet+    ( BitSet     , empty     , null     , insert+    , fromList     , delete     , member     , size@@ -28,34 +27,18 @@  import Prelude hiding ( null ) import Data.Bits+import Data.Data  --- | Map a value to an non-negative @Int@.------ For the implementation to give reliable results, it must be that if @hash x--- == hash y@, @x@ and @y@ are equivalent under the relevant relation used in--- the client code.  (We don't depend on equality, but the client code will--- certainly want to use the above sort of inference.)------ In fact, if the relevant relation is @==@, the following quickcheck--- test should pass, for arbitrary @x@ and @y@ of type @a@:------ @prop_hash x y =---     if hash x == hash y then x == y---     else x /= y---     && if x == y then hash x == hash y---        else hash x /= hash y@-class Hash a where-    hash :: a -> Int---- | The @Show@ instance kind of sucks.  It just shows the size paired with--- the internal @Integer@ representation.  A good show would probably show all--- the present hashes.-newtype BitSet a = BS { unBS :: (Int, Integer) }-    deriving (Eq)+data BitSet a = BS {-# UNPACK #-} !Int {-# UNPACK #-} !Integer+                deriving (Eq, Ord, Data, Typeable) -instance Show (BitSet a) where-    show s = "BitSet " ++ show (unBS s)+instance (Enum a, Show a) => Show (BitSet a) where+    show (BS _ i :: BitSet a) = "fromList " ++ show (f 0 i)+        where f _ 0 = []+              f n x = if testBit x 0+                      then (toEnum n :: a) : f (n+1) (shiftR x 1)+                      else f (n+1) (shiftR x 1)  -- | The empty bit set. empty :: BitSet a@@ -64,13 +47,16 @@ null :: BitSet a -> Bool  -- | /O(setBit on Integer)/ Insert an item into the bit set.-insert :: Hash a => a -> BitSet a -> BitSet a+insert :: Enum a => a -> BitSet a -> BitSet a +-- | /O(n * setBit on Integer)/ Make a @BitSet@ from a list of items.+fromList :: Enum a => [a] -> BitSet a+ -- | /O(clearBit on Integer)/ Delete an item from the bit set.-delete :: Hash a => a -> BitSet a -> BitSet a+delete :: Enum a => a -> BitSet a -> BitSet a  -- | /O(testBit on Integer)/ Ask whether the item is in the bit set.-member :: Hash a => a -> BitSet a -> Bool+member :: Enum a => a -> BitSet a -> Bool  -- | /O(1)/ The number of elements in the bit set. size :: BitSet a -> Int@@ -78,39 +64,26 @@  -- * Implementation -empty = BS (0, 0)+{-# INLINE empty #-}+empty = BS 0 0 -null (BS (n, _)) = n == 0+{-# INLINE null #-}+null (BS n _) = n == 0  {-# INLINE insert #-}-insert x s@(BS (count, i)) = BS $ (count', setBit i h)-    where count' = if h `memHash` s then count else count+1-          h      = hash x+insert x (BS count i) = BS count' (setBit i e)+    where count' = if testBit i e then count else count+1+          e      = fromEnum x +fromList xs = BS (length xs) (foldl (\i x -> setBit i (fromEnum x)) 0 xs)+ {-# INLINE delete #-}-delete x s@(BS (count, i)) = BS $ (count', clearBit i h)-    where count' = if h `memHash` s then count-1 else count-          h      = hash x+delete x (BS count i) = BS count' (clearBit i e)+    where count' = if testBit i e then count-1 else count+          e      = fromEnum x  {-# INLINE member #-}-member x s = hash x `memHash` s-memHash :: Int -> BitSet a -> Bool-{-# INLINE memHash #-}-memHash h (BS (_, i)) = testBit i h+member x (BS _ i) = testBit i (fromEnum x)  {-# INLINE size #-}-size (BS (count, _)) = count---- * Default instances--instance Hash Int where-    hash = id--instance Hash Integer where-    hash = fromIntegral---- Needs UndecidableInstances?--- instance Integral a => Hash a where---     hash = fromIntegral--    +size (BS count _) = count
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
− Setup.lhs
@@ -1,4 +0,0 @@-#! /usr/bin/env runhaskell--> import Distribution.Simple-> main = defaultMain
bitset.cabal view
@@ -1,5 +1,5 @@ Name:                bitset-Version:             0.6+Version:             1.0 Synopsis:            A functional data structure for efficient membership testing. Description:         A /bit set/ maintains a record of members from a type that can be mapped@@ -11,10 +11,13 @@ Author:              Denis Bueno Maintainer:          Denis Bueno <dbueno@gmail.com> Stability:           provisional+Cabal-Version:       >= 1.2.3 Build-Depends:       base, QuickCheck Build-type:          Simple  Exposed-modules:     Data.BitSet-Ghc-options:         -Wall+Build-depends:       base >= 4.0.0+Extensions:          ScopedTypeVariables, DeriveDataTypeable+Ghc-options:         -Wall -O2 Ghc-prof-options:    -prof -auto-all Extra-source-files:  tests/Properties.hs
tests/Properties.hs view
@@ -1,29 +1,35 @@ module Properties where +import Control.Monad( liftM ) import Prelude hiding ( null ) import Data.BitSet import Data.Foldable ( foldl' ) import Data.List ( nub ) import Test.QuickCheck+import System.IO+ import qualified Data.List as List    main :: IO () main = do-  check config prop_size-  check config prop_size_insert-  check config prop_size_delete-  check config prop_insert-  check config prop_delete-  check config prop_insDelIdempotent-  check config prop_delDelIdempotent-  check config prop_insInsIdempotent-  check config prop_extensional-  check config prop_empty+  dbgMsg "prop_size: " >> check config prop_size+  dbgMsg "prop_size_insert: " >> check config prop_size_insert+  dbgMsg "prop_size_delete: " >> check config prop_size_delete+  dbgMsg "prop_insert: " >> check config prop_insert+  dbgMsg "prop_delete: " >> check config prop_delete+  dbgMsg "prop_insDelIdempotent: " >> check config prop_insDelIdempotent+  dbgMsg "prop_delDelIdempotent: " >> check config prop_delDelIdempotent+  dbgMsg "prop_insInsIdempotent: " >> check config prop_insInsIdempotent+  dbgMsg "prop_extensional: " >> check config prop_extensional+  dbgMsg "prop_fromList: " >> check config prop_fromList+  dbgMsg "prop_empty: " >> check config prop_empty -config = defaultConfig{ configMaxTest = 1000 }+dbgMsg = hPutStr stderr +config = defaultConfig{ configMaxTest = 2000 }+ -- * Quickcheck properties  prop_size xs =@@ -70,12 +76,14 @@     where s   = foldr insert empty xsa           xsa = map abs xs :: [Int] +prop_fromList xs = all (`member` s) xsa+    where s   = fromList xsa+          xsa = map abs xs :: [Int]+ prop_empty x = not $ xa `member` empty     where xa = abs x :: Int   -instance (Arbitrary a, Hash a) => Arbitrary (BitSet a) where-    arbitrary = sized $ \n ->-                do xs <- vector n-                   return $ foldl' (flip insert) empty xs+instance (Arbitrary a, Enum a) => Arbitrary (BitSet a) where+    arbitrary = sized $ liftM fromList . vector