packages feed

hashable 1.1.1.0 → 1.1.2.0

raw patch · 3 files changed

+109/−49 lines, 3 filesdep +QuickCheckdep +hashabledep +randomdep ~textPVP ok

version bump matches the API change (PVP)

Dependencies added: QuickCheck, hashable, random, test-framework, test-framework-quickcheck2

Dependency ranges changed: text

API changes (from Hackage documentation)

+ Data.Hashable: instance (Integral a, Hashable a) => Hashable (Ratio a)
+ Data.Hashable: instance Hashable (StableName a)
+ Data.Hashable: instance Hashable Double
+ Data.Hashable: instance Hashable Float
+ Data.Hashable: instance Hashable Integer

Files

CHANGES view
@@ -1,5 +1,11 @@ Version 1.1.1.0 +* Improved instances for tuples and lists.++* Added instances for StableName, Float, Double, Integer, and Ratio.++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
Data/Hashable.hs view
@@ -37,10 +37,12 @@     , combine     ) where +import Control.Exception (assert) import Data.Bits (bitSize, shiftL, shiftR, xor) import Data.Int (Int8, Int16, Int32, Int64) import Data.Word (Word, Word8, Word16, Word32, Word64) import Data.List (foldl')+import Data.Ratio (Ratio, denominator, numerator) import qualified Data.ByteString as B import qualified Data.ByteString.Internal as B import qualified Data.ByteString.Unsafe as B@@ -51,7 +53,10 @@ import qualified Data.Text.Internal as T import qualified Data.Text.Lazy as LT import Foreign.C (CLong, CString)+import Foreign.Marshal.Utils (with) import Foreign.Ptr (Ptr, castPtr)+import Foreign.Storable (alignment, peek, sizeOf)+import System.IO.Unsafe (unsafePerformIO)  #if defined(__GLASGOW_HASKELL__) import Foreign.C.Types (CInt)@@ -62,6 +67,14 @@ import Control.Concurrent (ThreadId) #endif +#if defined(__GLASGOW_HASKELL__) || defined(__HUGS__)+import System.Mem.StableName+#endif++#include "MachDeps.h"++infixl 0 `combine`, `hashWithSalt`+ ------------------------------------------------------------------------ -- * Computing hash values @@ -132,55 +145,105 @@         | bitSize (undefined :: Int) == 64 = fromIntegral n         | otherwise = fromIntegral (n `xor` (n `shiftR` 32)) +instance Hashable Integer where+    hash = foldl' hashWithSalt 0 . go+      where+        go n | inBounds n = [fromIntegral n :: Int]+             | otherwise   = fromIntegral n : go (n `shiftR` WORD_SIZE_IN_BITS)+        maxInt = fromIntegral (maxBound :: Int)+        inBounds x = x >= fromIntegral (minBound :: Int) && x <= maxInt++instance (Integral a, Hashable a) => Hashable (Ratio a) where+    {-# SPECIALIZE instance Hashable (Ratio Integer) #-}+    hash a = hash (numerator a) `hashWithSalt` denominator a+    hashWithSalt s a = s `hashWithSalt` numerator a `hashWithSalt` denominator a++instance Hashable Float where+    hash x+        | isIEEE x =+            assert (sizeOf x >= sizeOf (0::Word32) &&+                    alignment x >= alignment (0::Word32)) $+            hash ((unsafePerformIO $ with x $ peek . castPtr) :: Word32)+        | otherwise = hash (show x)++instance Hashable Double where+    hash x+        | isIEEE x =+            assert (sizeOf x >= sizeOf (0::Word64) &&+                    alignment x >= alignment (0::Word64)) $+            hash ((unsafePerformIO $ with x $ peek . castPtr) :: Word64)+        | otherwise = hash (show x)+ instance Hashable Char where hash = fromEnum  instance Hashable a => Hashable (Maybe a) where     hash Nothing = 0-    hash (Just a) = 1 `combine` hash a+    hash (Just a) = 1 `hashWithSalt` a+    hashWithSalt s Nothing = s `combine` 0+    hashWithSalt s (Just a) = s `combine` 1 `hashWithSalt` a  instance (Hashable a, Hashable b) => Hashable (Either a b) where-    hash (Left a)  = 0 `combine` hash a-    hash (Right b) = 1 `combine` hash b+    hash (Left a)  = 0 `hashWithSalt` a+    hash (Right b) = 1 `hashWithSalt` b+    hashWithSalt s (Left a)  = s `combine` 0 `hashWithSalt` a+    hashWithSalt s (Right b) = s `combine` 1 `hashWithSalt` b  instance (Hashable a1, Hashable a2) => Hashable (a1, a2) where-    hash (a1, a2) = defaultSalt `combine` hash a1 `combine` hash a2+    hash (a1, a2) = hash a1 `hashWithSalt` a2+    hashWithSalt s (a1, a2) = s `hashWithSalt` a1 `hashWithSalt` a2  instance (Hashable a1, Hashable a2, Hashable a3) => Hashable (a1, a2, a3) where-    hash (a1, a2, a3) = defaultSalt `combine` hash a1 `combine` hash a2-                        `combine` hash a3+    hash (a1, a2, a3) = hash a1 `hashWithSalt` a2 `hashWithSalt` a3+    hashWithSalt s (a1, a2, a3) = s `hashWithSalt` a1 `hashWithSalt` a2+                        `hashWithSalt` a3  instance (Hashable a1, Hashable a2, Hashable a3, Hashable a4) =>          Hashable (a1, a2, a3, a4) where-    hash (a1, a2, a3, a4) = defaultSalt `combine` hash a1 `combine` hash a2-                            `combine` hash a3 `combine` hash a4+    hash (a1, a2, a3, a4) = hash a1 `hashWithSalt` a2+                            `hashWithSalt` a3 `hashWithSalt` a4+    hashWithSalt s (a1, a2, a3, a4) = s `hashWithSalt` a1 `hashWithSalt` a2+                            `hashWithSalt` a3 `hashWithSalt` 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) =-        defaultSalt `combine` hash a1 `combine` hash a2 `combine` hash a3-        `combine` hash a4 `combine` hash a5+        hash a1 `hashWithSalt` a2 `hashWithSalt` a3+        `hashWithSalt` a4 `hashWithSalt` a5+    hashWithSalt s (a1, a2, a3, a4, a5) =+        s `hashWithSalt` a1 `hashWithSalt` a2 `hashWithSalt` a3+        `hashWithSalt` a4 `hashWithSalt` 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) =-        defaultSalt `combine` hash a1 `combine` hash a2 `combine` hash a3-        `combine` hash a4 `combine` hash a5 `combine` hash a6+        hash a1 `hashWithSalt` a2 `hashWithSalt` a3+        `hashWithSalt` a4 `hashWithSalt` a5 `hashWithSalt` a6+    hashWithSalt s (a1, a2, a3, a4, a5, a6) =+        s `hashWithSalt` a1 `hashWithSalt` a2 `hashWithSalt` a3+        `hashWithSalt` a4 `hashWithSalt` a5 `hashWithSalt` 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) =-        defaultSalt `combine` hash a1 `combine` hash a2 `combine` hash a3-        `combine` hash a4 `combine` hash a5 `combine` hash a6 `combine` hash a7+        hash a1 `hashWithSalt` a2 `hashWithSalt` a3+        `hashWithSalt` a4 `hashWithSalt` a5 `hashWithSalt` a6 `hashWithSalt` a7+    hashWithSalt s (a1, a2, a3, a4, a5, a6, a7) =+        s `hashWithSalt` a1 `hashWithSalt` a2 `hashWithSalt` a3+        `hashWithSalt` a4 `hashWithSalt` a5 `hashWithSalt` a6 `hashWithSalt` a7 +#if defined(__GLASGOW_HASKELL__) || defined(__HUGS__)+instance Hashable (StableName a) where+    hash = hashStableName+#endif+ -- | Default salt for hashing string like types. stringSalt :: Int stringSalt = 5381  instance Hashable a => Hashable [a] where     {-# SPECIALIZE instance Hashable [Char] #-}-    hash = foldl' hashAndCombine stringSalt-    hashWithSalt = foldl' hashAndCombine+    hashWithSalt = foldl' hashWithSalt  -- | Compute the hash of a ThreadId.  For GHC, we happen to know a -- trick to make this fast.@@ -197,32 +260,24 @@     hash = hashThreadId     {-# INLINE hash #-} -hashAndCombine :: Hashable h => Int -> h -> Int-hashAndCombine acc h = acc `combine` hash h- instance Hashable B.ByteString where-    hash bs = B.inlinePerformIO $-              B.unsafeUseAsCStringLen bs $ \(p, len) ->-              hashPtr p (fromIntegral len)-+    hash = hashWithSalt stringSalt     hashWithSalt salt bs = B.inlinePerformIO $                            B.unsafeUseAsCStringLen bs $ \(p, len) ->                            hashPtrWithSalt p (fromIntegral len) salt  instance Hashable BL.ByteString where-    hash = BL.foldlChunks hashWithSalt stringSalt+    hash = 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)-+    hash = hashWithSalt stringSalt     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 hashWithSalt stringSalt+    hash = hashWithSalt stringSalt     hashWithSalt = LT.foldlChunks hashWithSalt  ------------------------------------------------------------------------@@ -231,9 +286,9 @@ -- $blocks -- -- The functions below can be used when creating new instances of--- 'Hashable'.  For example, the 'hash' method for many string-like--- types can be defined in terms of either 'hashPtr' or--- 'hashByteArray'.  Here's how you could implement an instance for+-- 'Hashable'.  For example, the 'hashWithSalt' method for many string-like+-- types can be defined in terms of either 'hashPtrWithSalt' or+-- 'hashByteArrayWithSalt'.  Here's how you could implement an instance for -- the 'B.ByteString' data type, from the @bytestring@ package: -- -- > import qualified Data.ByteString as B@@ -243,16 +298,16 @@ -- > import Foreign.Ptr (castPtr) -- > -- > instance Hashable B.ByteString where--- >     hash bs = B.inlinePerformIO $--- >               B.unsafeUseAsCStringLen bs $ \ (p, len) ->--- >               hashPtr p (fromIntegral len)+-- >     hashWithSalt salt bs = B.inlinePerformIO $+-- >                            B.unsafeUseAsCStringLen bs $ \(p, len) ->+-- >                            hashPtrWithSalt p (fromIntegral len) salt -- -- The 'combine' function can be used to implement 'Hashable' -- instances for data types with more than one field, using this -- recipe: -- -- > instance (Hashable a, Hashable b) => Hashable (Foo a b) where--- >     hash (Foo a b) = 17 `combine` hash a `combine` hash b+-- >     hashWithSalt s (Foo a b) = s `hashWithSalt` a `hashWithSalt` b -- -- A nonzero seed is used so the hash value will be affected by -- initial fields whose hash value is zero.  If no seed was provided,
hashable.cabal view
@@ -1,5 +1,5 @@ Name:                hashable-Version:             1.1.1.0+Version:             1.1.2.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@@ -35,20 +35,19 @@   if impl(ghc >= 6.8)     Ghc-options: -fwarn-tabs --- -- Commented out until cabal-install release.--- Test-suite tests---   Type:              exitcode-stdio-1.0---   Hs-source-dirs:    tests---   Main-is:           Properties.hs---   Build-depends:     base >= 4.0 && < 5,---                      hashable,---                      test-framework >= 0.3.3 && < 0.4,---                      test-framework-quickcheck2 >= 0.2.9 && < 0.3,---                      QuickCheck >= 2.4.0.1,---                      random == 1.0.*,---                      text >= 0.11.0.5+Test-suite tests+  Type:              exitcode-stdio-1.0+  Hs-source-dirs:    tests+  Main-is:           Properties.hs+  Build-depends:     base >= 4.0 && < 5,+                     hashable,+                     test-framework >= 0.3.3 && < 0.4,+                     test-framework-quickcheck2 >= 0.2.9 && < 0.3,+                     QuickCheck >= 2.4.0.1,+                     random == 1.0.*,+                     text >= 0.11.0.5 ---   Ghc-options:       -Wall+  Ghc-options:       -Wall  source-repository head   type:     git