@@ -47,6 +47,7 @@ module Data.HashMap.Internal
4747 , findWithDefault
4848 , lookupDefault
4949 , (!)
50+ , lookupKey
5051 , insert
5152 , insertWith
5253 , unsafeInsert
@@ -784,6 +785,40 @@ lookupDefault = findWithDefault
784785
785786infixl 9 !
786787
788+ -- | \(O(\log n)\) For a given key, return the equal key stored in the map,
789+ -- if present, otherwise return 'Nothing'.
790+ --
791+ -- This function can be used for /interning/, i.e. to reduce memory usage.
792+ lookupKey :: Hashable k => k -> HashMap k v -> Maybe k
793+ lookupKey k = \ m -> fromMaybe# (lookupKeyInSubtree# 0 (hash k) k m)
794+ where
795+ fromMaybe# (# (##) | # ) = Nothing
796+ fromMaybe# (# | a # ) = Just a
797+ {-# INLINE lookupKey #-}
798+
799+ lookupKeyInSubtree# :: Eq k => Shift -> Hash -> k -> HashMap k v -> (# (## ) | k # )
800+ lookupKeyInSubtree# ! s ! hx kx = \ case
801+ Empty -> (# (##) | # )
802+ Leaf hy (L ky _)
803+ | hx == hy && kx == ky -> (# | ky # )
804+ | otherwise -> (# (##) | # )
805+ BitmapIndexed b ary
806+ | m .&. b == 0 -> (# (##) | # )
807+ | otherwise -> case A. index# ary i of
808+ (# st # ) -> lookupKeyInSubtree# (nextShift s) hx kx st
809+ where
810+ m = mask hx s
811+ i = sparseIndex b m
812+ Full ary -> case A. index# ary (index hx s) of
813+ (# st # ) -> lookupKeyInSubtree# (nextShift s) hx kx st
814+ Collision hy ary
815+ | hx == hy
816+ , Just i <- indexOf kx ary
817+ , (# L ky _ # ) <- A. index# ary i
818+ -> (# | ky # )
819+ | otherwise -> (# (##) | # )
820+ {-# INLINABLE lookupKeyInSubtree# #-}
821+
787822-- | Create a 'Collision' value with two 'Leaf' values.
788823collision :: Hash -> Leaf k v -> Leaf k v -> HashMap k v
789824collision h ! e1 ! e2 =
0 commit comments