Doug Burke avatar Doug Burke committed 4e757fa

Initial attempt at supporting hashable 1.2.0 as well as 1.1.x

Comments (0)

Files changed (6)

src/Data/Interned/URI.hs

 -- Rather than access the URI components, just use the reverse of the
 -- string representation of the URI.
 instance Hashable (Description InternedURI) where
+#if MIN_VERSION_hashable(1,2,0)
+#else
   hash = hashWithSalt 5381 -- use the stringSalt value from Data.Hashable
+#endif
   hashWithSalt salt (DU u) = hashWithSalt salt ((reverse . show) u)
 
 iuCache :: Cache InternedURI

src/Swish/GraphClass.hs

+{-# LANGUAGE CPP #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE DeriveFunctor #-}
 {-# LANGUAGE DeriveFoldable #-}
 --
 --  Maintainer  :  Douglas Burke
 --  Stability   :  experimental
---  Portability :  DeriveFunctor, DeriveFoldable, DeriveTraversable, MultiParamTypeClasses
+--  Portability :  CPP, DeriveFunctor, DeriveFoldable, DeriveTraversable, MultiParamTypeClasses
 --
 --  This module defines a Labelled Directed Graph and Label classes,
 --  and the Arc datatype.
 type ArcSet lb = S.Set (Arc lb)
 
 instance (Hashable lb) => Hashable (Arc lb) where
+#if MIN_VERSION_hashable(1,2,0) 
+#else
   hash (Arc s p o) = hash s `hashWithSalt` p `hashWithSalt` o
+#endif
   hashWithSalt salt (Arc s p o) = salt `hashWithSalt` s `hashWithSalt` p `hashWithSalt` o
 
 -- | Create an arc.

src/Swish/GraphMatch.hs

 import Control.Arrow (second)
 
 import Data.Function (on)
-import Data.Hashable (combine)
+import Data.Hashable (hashWithSalt)
 import Data.List (foldl', sortBy, groupBy, partition)
 import Data.Ord (comparing)
 import Data.Word
     makeLabel locnam = error $ "makeLabel for ScopedLabel: "++locnam
     labelIsVar (ScopedLabel _ lab)   = labelIsVar lab
     labelHash seed (ScopedLabel scope lab)
-        | labelIsVar lab    = seed `combine` scope -- MH.hash seed $ show scope ++ "???"
+        | labelIsVar lab    = seed `hashWithSalt` scope
         | otherwise         = labelHash seed lab
 
 instance (Label lb) => Eq (ScopedLabel lb) where
 initVal :: (Label lb) => lb -> Word32
 initVal = fromIntegral . hashVal 0
 
-hashVal :: (Label lb) => Int -> lb -> Int
+hashVal :: (Label lb) => Word32 -> lb -> Int
 hashVal seed lab =
-  if labelIsVar lab then seed `combine` 23 else labelHash seed lab
-  -- if labelIsVar lab then hash seed "???" else labelHash seed lab
+  if labelIsVar lab then 23 `hashWithSalt` seed else labelHash (fromIntegral seed) lab
 
 -- | Return the equivalence classes of the supplied nodes 
 -- using the label map.
     where
         gen'                = gen+1
         newEntries          = [ (l, (gen', fromIntegral (newIndex l))) | l <- ls ]
+	-- TODO: should review this given the changes to the hash code
+        --       since it was re-written
         newIndex l
             | labelIsVar l  = mapAdjacent l                 -- adjacency classifies variable labels
-            | otherwise     = hashVal (fromIntegral gen) l  -- otherwise rehash (to disentangle collisions)
-        -- mapAdjacent l       = sum (sigsOver l) `rem` hashModulus
-        mapAdjacent l       = sum (sigsOver l) `combine` hashModulus -- is this a sensible replacement for `rem` MH.hashModulus        
+            | otherwise     = fromIntegral $ hashVal gen l  -- otherwise rehash (to disentangle collisions)
+
+	-- mapAdjacent used to use `rem` hashModulus
+        mapAdjacent l       = hashModulus `hashWithSalt` sum (sigsOver l)
 
         gls = S.toList gs
 
     map (sigCalc . arcToTriple) 
     where
         sigCalc (s,p,o)  =
-            fromIntegral ( labelVal2 s +
-                           labelVal2 p * 3 +
-                           labelVal2 o * 5 )
-            `combine` hashModulus
-            -- `rem` hashModulus
+	    hashModulus `hashWithSalt`
+              ( labelVal2 s +
+                labelVal2 p * 3 +
+                labelVal2 o * 5 )
           
         labelVal         = mapLabelIndex lmap
         labelVal2        = uncurry (*) . labelVal

src/Swish/GraphMem.hs

+{-# LANGUAGE CPP #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 
 --
 --  Maintainer  :  Douglas Burke
 --  Stability   :  experimental
---  Portability :  FlexibleInstances, MultiParamTypeClasses
+--  Portability :  CPP, FlexibleInstances, MultiParamTypeClasses
 --
 --  This module defines a simple memory-based graph instance.
 --
 import Swish.GraphClass
 import Swish.GraphMatch
 
-import Data.Hashable (Hashable(..), combine)
+import Data.Hashable (Hashable(..))
 import Data.Monoid (Monoid(..))
 import Data.Ord (comparing)
 
     | LV String
 
 instance Hashable LabelMem where
+  hashWithSalt salt (LF l) = salt `hashWithSalt` (1::Int) `hashWithSalt` l
+  hashWithSalt salt (LV l) = salt `hashWithSalt` (2::Int) `hashWithSalt` l
+#if !MIN_VERSION_hashable(1,2,0)
   hash (LF l) = 1 `hashWithSalt` l
   hash (LV l) = 2 `hashWithSalt` l
-  hashWithSalt salt (LF l) = salt `combine` 1 `hashWithSalt` l
-  hashWithSalt salt (LV l) = salt `combine` 2 `hashWithSalt` l
+#endif
 
 instance Label LabelMem where
     labelIsVar (LV _)   = True
       base >=3 && < 5,
       containers >= 0.4 && < 0.6,
       filepath >= 1.1 && < 1.4,
-      hashable == 1.1.*,
+      -- hashable == 1.1.*,
+      hashable >= 1.1 && < 1.3,
       mtl >= 2 && < 3,
       network >= 2.2 && < 2.5,
       old-locale == 1.0.*, 

tests/GraphTest.hs

 import TestHelpers (runTestSuite, testEq, testNe)
 
 import Data.Function (on)
-import Data.Hashable (combine)
+import Data.Hashable (hashWithSalt)
 import Data.List (sort, sortBy, elemIndex)
 import Data.Maybe (fromJust)
 import Data.Ord (comparing)
 -- assignLabels :: (Label lb) => [lb] -> LabelMap lb -> LabelMap lb
 
 bhash :: Word32
-bhash = 23
+-- bhash = 23 -- before trying to support Hashable 1.2.0
+bhash = 3730297980
 
 -- since the hashing is now done by hashable, is it worth checking
--- the hash values directly?
+-- the hash values directly? It would perhaps be better to just
+-- quickcheck that values get sorted.
 
 -- copy of internal code in GraphMatch
-toHash :: (Label lb) => Int -> lb -> Word32
+toHash :: (Label lb) => Word32 -> lb -> Word32
 toHash s lbl = 
     fromIntegral $
       if labelIsVar lbl 
-        then s `combine` 23
-        else labelHash s lbl
+        then 23 `hashWithSalt` s
+        else labelHash (fromIntegral s) lbl
 
 l1hash, l4hash, l10hash :: Word32
 l1hash = toHash 0 l1
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.