Skip to content

Commit 080c4db

Browse files
committed
Add Hashable1/2 instances
1 parent fc2185f commit 080c4db

File tree

3 files changed

+47
-6
lines changed

3 files changed

+47
-6
lines changed

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
* `Eq (HashSet a)` doesn't require `Hashable a` anymore, only `Eq a`.
66

7+
* Add `Hashable1/2` with `hashable-1.2.6.0`
8+
79
## 0.2.7.2
810

911
* Don't use -fregs-graphs

Data/HashMap/Base.hs

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,11 @@ import qualified GHC.Exts as Exts
130130
import Data.Functor.Classes
131131
#endif
132132

133+
#if MIN_VERSION_hashable(1,2,5)
134+
import qualified Data.Hashable.Lifted as H
135+
#endif
136+
137+
-- | A set of values. A set cannot contain duplicate values.
133138
------------------------------------------------------------------------
134139

135140
-- | Convenience function. Compute a hash value for the given value.
@@ -309,6 +314,34 @@ equalKeys eq t1 t2 = go (toList' t1 []) (toList' t2 [])
309314

310315
leafEq (L k _) (L k' _) = eq k k'
311316

317+
#if MIN_VERSION_hashable(1,2,5)
318+
instance H.Hashable2 HashMap where
319+
liftHashWithSalt2 hk hv salt hm = go salt (toList' hm [])
320+
where
321+
-- go :: Int -> [HashMap k v] -> Int
322+
go s [] = s
323+
go s (Leaf _ l : tl)
324+
= s `hashLeafWithSalt` l `go` tl
325+
-- For collisions we hashmix hash value
326+
-- and then array of values' hashes sorted
327+
go s (Collision h a : tl)
328+
= (s `H.hashWithSalt` h) `hashCollisionWithSalt` a `go` tl
329+
go s (_ : tl) = s `go` tl
330+
331+
-- hashLeafWithSalt :: Int -> Leaf k v -> Int
332+
hashLeafWithSalt s (L k v) = (s `hk` k) `hv` v
333+
334+
-- hashCollisionWithSalt :: Int -> A.Array (Leaf k v) -> Int
335+
hashCollisionWithSalt s
336+
= L.foldl' H.hashWithSalt s . arrayHashesSorted s
337+
338+
-- arrayHashesSorted :: Int -> A.Array (Leaf k v) -> [Int]
339+
arrayHashesSorted s = L.sort . L.map (hashLeafWithSalt s) . A.toList
340+
341+
instance (Hashable k) => H.Hashable1 (HashMap k) where
342+
liftHashWithSalt = H.liftHashWithSalt2 H.hashWithSalt
343+
#endif
344+
312345
instance (Hashable k, Hashable v) => Hashable (HashMap k v) where
313346
hashWithSalt salt hm = go salt (toList' hm [])
314347
where
@@ -327,13 +360,10 @@ instance (Hashable k, Hashable v) => Hashable (HashMap k v) where
327360

328361
hashCollisionWithSalt :: Int -> A.Array (Leaf k v) -> Int
329362
hashCollisionWithSalt s
330-
= L.foldl' H.hashWithSalt s . arrayHashesSorted
331-
332-
arrayHashesSorted :: A.Array (Leaf k v) -> [Int]
333-
arrayHashesSorted = L.sort . L.map leafValueHash . A.toList
363+
= L.foldl' H.hashWithSalt s . arrayHashesSorted s
334364

335-
leafValueHash :: Leaf k v -> Int
336-
leafValueHash (L _ v) = H.hash v
365+
arrayHashesSorted :: Int -> A.Array (Leaf k v) -> [Int]
366+
arrayHashesSorted s = L.sort . L.map (hashLeafWithSalt s) . A.toList
337367

338368
-- Helper to get 'Leaf's and 'Collision's as a list.
339369
toList' :: HashMap k v -> [HashMap k v] -> [HashMap k v]

Data/HashSet.hs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ import qualified GHC.Exts as Exts
9797
import Data.Functor.Classes
9898
#endif
9999

100+
#if MIN_VERSION_hashable(1,2,5)
101+
import qualified Data.Hashable.Lifted as H
102+
#endif
103+
100104
-- | A set of values. A set cannot contain duplicate values.
101105
newtype HashSet a = HashSet {
102106
asMap :: HashMap a ()
@@ -166,6 +170,11 @@ instance (Data a, Eq a, Hashable a) => Data (HashSet a) where
166170
dataTypeOf _ = hashSetDataType
167171
dataCast1 f = gcast1 f
168172

173+
#if MIN_VERSION_hashable(1,2,6)
174+
instance H.Hashable1 HashSet where
175+
liftHashWithSalt h s = H.liftHashWithSalt2 h hashWithSalt s . asMap
176+
#endif
177+
169178
instance (Hashable a) => Hashable (HashSet a) where
170179
hashWithSalt salt = hashWithSalt salt . asMap
171180

0 commit comments

Comments
 (0)