hashable 1.1.0.0 → 1.1.1.0
raw patch · 4 files changed
+74/−44 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.Hashable: hashWithSalt :: Hashable a => Int -> a -> Int
Files
- CHANGES +16/−0
- Data/Hashable.hs +53/−39
- hashable.cabal +1/−1
- tests/Properties.hs +4/−4
CHANGES view
@@ -1,9 +1,25 @@+Version 1.1.1.0++* Added hashWithSalt, which allows the user to create different hash+ values for the same input by providing different seeds. This is+ useful for application like Cuckoo hashing which need a family of+ hash functions.++* Fixed a bug in the Hashable instance for Int64/Word64 on 32-bit+ platforms.++* Improved resilience to leading zero in the input being hashed.+ Version 1.1.0.0 * Added instance for: strict and lazy Texts, ThreadId+ * Added hashPtrWithSalt and hashByteArrayWithSalt.+ * Faster ByteArray# hashing.+ * Fixed a signedness bug that affected ByteString.+ * Fix ByteString hashing to work correctly on both 32 and 64-bit platforms.
Data/Hashable.hs view
@@ -8,7 +8,7 @@ -- (c) Johan Tibell 2011 -- (c) Bryan O'Sullivan 2011 -- License : BSD-style--- Maintainer : fox@ucw.cz+-- Maintainer : johan.tibell@gmail.com -- Stability : provisional -- Portability : portable --@@ -65,7 +65,15 @@ ------------------------------------------------------------------------ -- * Computing hash values +-- | A default salt used in the default implementation of+-- 'hashWithSalt'.+defaultSalt :: Int+defaultSalt = 17+{-# INLINE defaultSalt #-}+ -- | The class of types that can be converted to a hash value.+--+-- Minimal implementation: 'hash' or 'hashWithSalt'. class Hashable a where -- | Return a hash value for the argument. --@@ -87,7 +95,20 @@ -- may improve the performance of hashing-based data -- structures. hash :: a -> Int+ hash = hashWithSalt defaultSalt + -- | Return a hash value for the argument, using the given salt.+ --+ -- This method can be used to compute different hash values for+ -- the same input by providing a different salt in each+ -- application of the method.+ --+ -- The contract for 'hashWithSalt' is the same as for 'hash', with+ -- the additional requirement that any instance that defines+ -- 'hashWithSalt' must make use of the salt in its implementation.+ hashWithSalt :: Int -> a -> Int+ hashWithSalt salt x = salt `combine` hash x+ instance Hashable () where hash _ = 0 instance Hashable Bool where hash x = case x of { True -> 1; False -> 0 }@@ -98,7 +119,7 @@ instance Hashable Int32 where hash = fromIntegral instance Hashable Int64 where hash n- | bitSize n == 64 = fromIntegral n+ | bitSize (undefined :: Int) == 64 = fromIntegral n | otherwise = fromIntegral (fromIntegral n `xor` (fromIntegral n `shiftR` 32 :: Word64)) @@ -108,7 +129,7 @@ instance Hashable Word32 where hash = fromIntegral instance Hashable Word64 where hash n- | bitSize n == 64 = fromIntegral n+ | bitSize (undefined :: Int) == 64 = fromIntegral n | otherwise = fromIntegral (n `xor` (n `shiftR` 32)) instance Hashable Char where hash = fromEnum@@ -122,38 +143,44 @@ hash (Right b) = 1 `combine` hash b instance (Hashable a1, Hashable a2) => Hashable (a1, a2) where- hash (a1, a2) = hash a1 `combine` hash a2+ hash (a1, a2) = defaultSalt `combine` hash a1 `combine` hash a2 instance (Hashable a1, Hashable a2, Hashable a3) => Hashable (a1, a2, a3) where- hash (a1, a2, a3) = hash a1 `combine` hash a2 `combine` hash a3+ hash (a1, a2, a3) = defaultSalt `combine` hash a1 `combine` hash a2+ `combine` hash a3 instance (Hashable a1, Hashable a2, Hashable a3, Hashable a4) => Hashable (a1, a2, a3, a4) where- hash (a1, a2, a3, a4) = hash a1 `combine` hash a2 `combine` hash a3- `combine` hash a4+ hash (a1, a2, a3, a4) = defaultSalt `combine` hash a1 `combine` hash a2+ `combine` hash a3 `combine` hash a4 instance (Hashable a1, Hashable a2, Hashable a3, Hashable a4, Hashable a5) => Hashable (a1, a2, a3, a4, a5) where hash (a1, a2, a3, a4, a5) =- hash a1 `combine` hash a2 `combine` hash a3 `combine` hash a4 `combine`- hash a5+ defaultSalt `combine` hash a1 `combine` hash a2 `combine` hash a3+ `combine` hash a4 `combine` hash a5 instance (Hashable a1, Hashable a2, Hashable a3, Hashable a4, Hashable a5, Hashable a6) => Hashable (a1, a2, a3, a4, a5, a6) where hash (a1, a2, a3, a4, a5, a6) =- hash a1 `combine` hash a2 `combine` hash a3 `combine` hash a4 `combine`- hash a5 `combine` hash a6+ defaultSalt `combine` hash a1 `combine` hash a2 `combine` hash a3+ `combine` hash a4 `combine` hash a5 `combine` hash a6 instance (Hashable a1, Hashable a2, Hashable a3, Hashable a4, Hashable a5, Hashable a6, Hashable a7) => Hashable (a1, a2, a3, a4, a5, a6, a7) where hash (a1, a2, a3, a4, a5, a6, a7) =- hash a1 `combine` hash a2 `combine` hash a3 `combine` hash a4 `combine`- hash a5 `combine` hash a6 `combine` hash a7+ defaultSalt `combine` hash a1 `combine` hash a2 `combine` hash a3+ `combine` hash a4 `combine` hash a5 `combine` hash a6 `combine` hash a7 +-- | Default salt for hashing string like types.+stringSalt :: Int+stringSalt = 5381+ instance Hashable a => Hashable [a] where {-# SPECIALIZE instance Hashable [Char] #-}- hash = foldl' hashAndCombine 0+ hash = foldl' hashAndCombine stringSalt+ hashWithSalt = foldl' hashAndCombine -- | Compute the hash of a ThreadId. For GHC, we happen to know a -- trick to make this fast.@@ -178,38 +205,25 @@ B.unsafeUseAsCStringLen bs $ \(p, len) -> hashPtr p (fromIntegral len) --- The arguments to this function are flipped to make the function--- easier to use with a left fold.---- | Compute a hash value for this 'B.ByteString', using an initial--- salt.-hashByteStringWithSalt :: Int -- ^ salt- -> B.ByteString -- ^ data to hash- -> Int -- ^ hash value-hashByteStringWithSalt salt bs =- B.inlinePerformIO $ B.unsafeUseAsCStringLen bs $ \(p, len) ->- hashPtrWithSalt p (fromIntegral len) salt+ hashWithSalt salt bs = B.inlinePerformIO $+ B.unsafeUseAsCStringLen bs $ \(p, len) ->+ hashPtrWithSalt p (fromIntegral len) salt instance Hashable BL.ByteString where- hash = BL.foldlChunks hashByteStringWithSalt 0+ hash = BL.foldlChunks hashWithSalt stringSalt+ hashWithSalt = BL.foldlChunks hashWithSalt instance Hashable T.Text where hash (T.Text arr off len) = hashByteArray (TA.aBA arr) (off `shiftL` 1) (len `shiftL` 1) --- The arguments to this function are flipped to make the function--- easier to use with a left fold.---- | Compute a hash value for this 'B.Text', using an initial--- salt.-hashTextWithSalt :: Int -- ^ salt- -> T.Text -- ^ data to hash- -> Int -- ^ hash value-hashTextWithSalt salt (T.Text arr off len) =- hashByteArrayWithSalt (TA.aBA arr) (off `shiftL` 1) (len `shiftL` 1) salt+ hashWithSalt salt (T.Text arr off len) =+ hashByteArrayWithSalt (TA.aBA arr) (off `shiftL` 1) (len `shiftL` 1)+ salt instance Hashable LT.Text where- hash = LT.foldlChunks hashTextWithSalt 0+ hash = LT.foldlChunks hashWithSalt stringSalt+ hashWithSalt = LT.foldlChunks hashWithSalt ------------------------------------------------------------------------ -- * Creating new instances@@ -250,7 +264,7 @@ hashPtr :: Ptr a -- ^ pointer to the data to hash -> Int -- ^ length, in bytes -> IO Int -- ^ hash value-hashPtr p len = hashPtrWithSalt p len 0+hashPtr p len = hashPtrWithSalt p len stringSalt -- | Compute a hash value for the content of this pointer, using an -- initial salt.@@ -277,7 +291,7 @@ -> Int -- ^ offset, in bytes -> Int -- ^ length, in bytes -> Int -- ^ hash value-hashByteArray ba0 off len = hashByteArrayWithSalt ba0 off len 0+hashByteArray ba0 off len = hashByteArrayWithSalt ba0 off len stringSalt {-# INLINE hashByteArray #-} -- | Compute a hash value for the content of this 'ByteArray#', using
hashable.cabal view
@@ -1,5 +1,5 @@ Name: hashable-Version: 1.1.0.0+Version: 1.1.1.0 Synopsis: A class for types that can be converted to a hash value Description: This package defines a class, 'Hashable', for types that can be converted to a hash value. This class
tests/Properties.hs view
@@ -6,7 +6,7 @@ module Main (main) where -import Data.Hashable (hash, hashByteArray, hashPtr)+import Data.Hashable (Hashable(hash), hashByteArray, hashPtr) import qualified Data.Text as T import qualified Data.Text.Lazy as L import Foreign (unsafePerformIO)@@ -15,7 +15,7 @@ writeWord8Array#) import GHC.ST (ST(..), runST) import GHC.Word (Word8(..))-import Test.QuickCheck+import Test.QuickCheck hiding ((.&.)) import Test.Framework (Test, defaultMain, testGroup) import Test.Framework.Providers.QuickCheck2 (testProperty) @@ -37,11 +37,11 @@ -- | Content equality implies hash equality. pText :: T.Text -> T.Text -> Bool-pText a b = (a == b) == (hash a == hash b)+pText a b = if (a == b) then (hash a == hash b) else True -- | Content equality implies hash equality. pTextLazy :: L.Text -> L.Text -> Bool-pTextLazy a b = (a == b) == (hash a == hash b)+pTextLazy a b = if (a == b) then (hash a == hash b) else True -- | A small positive integer. newtype ChunkSize = ChunkSize { unCS :: Int }