Skip to content

Commit 206b769

Browse files
committed
Fix Hashable property
1 parent 0a13436 commit 206b769

File tree

2 files changed

+23
-10
lines changed

2 files changed

+23
-10
lines changed

Data/HashMap/Base.hs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ import Control.DeepSeq (NFData(rnf))
9898
import Control.Monad.ST (ST)
9999
import Data.Bits ((.&.), (.|.), complement)
100100
import Data.Data hiding (Typeable)
101+
import Data.Ord (comparing)
101102
import qualified Data.Foldable as Foldable
102103
import qualified Data.List as L
103104
import GHC.Exts ((==#), build, reallyUnsafePtrEquality#)
@@ -201,9 +202,6 @@ instance Traversable (HashMap k) where
201202
instance (Eq k, Eq v) => Eq (HashMap k v) where
202203
(==) = equal
203204

204-
instance (Hashable k, Hashable v) => Hashable (HashMap k v) where
205-
hashWithSalt = foldlWithKey' (\h k v -> h `H.hashWithSalt` k `H.hashWithSalt` v)
206-
207205
equal :: (Eq k, Eq v) => HashMap k v -> HashMap k v -> Bool
208206
equal t1 t2 = go (toList' t1 []) (toList' t2 [])
209207
where
@@ -221,11 +219,26 @@ equal t1 t2 = go (toList' t1 []) (toList' t2 [])
221219
go [] [] = True
222220
go _ _ = False
223221

224-
toList' (BitmapIndexed _ ary) a = A.foldr toList' a ary
225-
toList' (Full ary) a = A.foldr toList' a ary
226-
toList' l@(Leaf _ _) a = l : a
227-
toList' c@(Collision _ _) a = c : a
228-
toList' Empty a = a
222+
instance (Hashable k, Ord k, Hashable v) => Hashable (HashMap k v) where
223+
hashWithSalt salt = L.foldl' (\h (L k v) -> h `H.hashWithSalt` k `H.hashWithSalt` v) salt . toList''
224+
where
225+
-- Order 'Leaf' s with (hash, k) ordering
226+
toList'' :: HashMap k v -> [Leaf k v]
227+
toList'' hm = concatMap f (toList' hm [])
228+
f :: HashMap k v -> [Leaf k v]
229+
f (Leaf _ l) = [l]
230+
f (Collision _ a) = L.sortBy (comparing leafKey) (A.toList a)
231+
f _ = []
232+
leafKey :: Leaf k v -> k
233+
leafKey (L k _) = k
234+
235+
-- Helper to get 'Leaf's and 'Collision's as a list.
236+
toList' :: HashMap k v -> [HashMap k v] -> [HashMap k v]
237+
toList' (BitmapIndexed _ ary) a = A.foldr toList' a ary
238+
toList' (Full ary) a = A.foldr toList' a ary
239+
toList' l@(Leaf _ _) a = l : a
240+
toList' c@(Collision _ _) a = c : a
241+
toList' Empty a = a
229242

230243
-- Helper function to detect 'Leaf's and 'Collision's.
231244
isLeafOrCollision :: HashMap k v -> Bool

Data/HashSet.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ instance (Data a, Eq a, Hashable a) => Data (HashSet a) where
136136
dataTypeOf _ = hashSetDataType
137137
dataCast1 f = gcast1 f
138138

139-
instance (Hashable a) => Hashable (HashSet a) where
140-
hashWithSalt = foldl' hashWithSalt
139+
instance (Hashable a, Ord a) => Hashable (HashSet a) where
140+
hashWithSalt salt = hashWithSalt salt . asMap
141141

142142
fromListConstr :: Constr
143143
fromListConstr = mkConstr hashSetDataType "fromList" [] Prefix

0 commit comments

Comments
 (0)