@@ -151,31 +151,33 @@ module Data.HashMap.Internal
151151 , adjust #
152152 ) where
153153
154- import Data.Traversable -- MicroHs needs this since its Prelude does not have Foldable&Traversable.
155- -- It's harmless for GHC, and putting it first avoid a warning.
156-
157- import Control.Applicative (Const (.. ))
158- import Control.DeepSeq (NFData (.. ), NFData1 (.. ), NFData2 (.. ))
159- import Control.Monad.ST (ST , runST )
160- import Data.Bifoldable (Bifoldable (.. ))
161- import Data.Bits (complement , countTrailingZeros , popCount ,
162- shiftL , unsafeShiftL , unsafeShiftR , (.&.) ,
163- (.|.) )
164- import Data.Coerce (coerce )
165- import Data.Data (Constr , Data (.. ), DataType )
166- import Data.Functor.Classes (Eq1 (.. ), Eq2 (.. ), Ord1 (.. ), Ord2 (.. ),
167- Read1 (.. ), Show1 (.. ), Show2 (.. ))
168- import Data.Functor.Identity (Identity (.. ))
169- import Data.Hashable (Hashable )
170- import Data.Hashable.Lifted (Hashable1 , Hashable2 )
171- import Data.HashMap.Internal.List (isPermutationBy , unorderedCompare )
172- import Data.Maybe (isNothing )
173- import Data.Semigroup (Semigroup (.. ), stimesIdempotentMonoid )
174- import GHC.Exts (Int (.. ), Int #, TYPE , (==#) )
175- import GHC.Stack (HasCallStack )
176- import Prelude hiding (Foldable (.. ), filter , lookup , map ,
177- pred )
178- import Text.Read hiding (step )
154+ -- MicroHs needs this import since its Prelude does not have Foldable&Traversable.
155+ -- It's harmless for GHC, and putting it first avoids a warning.
156+ import Data.Traversable
157+
158+ import Control.Applicative (Const (.. ))
159+ import Control.DeepSeq (NFData (.. ), NFData1 (.. ), NFData2 (.. ))
160+ import Control.Monad.ST (ST , runST )
161+ import Data.Bifoldable (Bifoldable (.. ))
162+ import Data.Bits (complement , countTrailingZeros , popCount ,
163+ shiftL , unsafeShiftL , unsafeShiftR , (.&.) ,
164+ (.|.) )
165+ import Data.Coerce (coerce )
166+ import Data.Data (Constr , Data (.. ), DataType )
167+ import Data.Functor.Classes (Eq1 (.. ), Eq2 (.. ), Ord1 (.. ), Ord2 (.. ),
168+ Read1 (.. ), Show1 (.. ), Show2 (.. ))
169+ import Data.Functor.Identity (Identity (.. ))
170+ import Data.Hashable (Hashable )
171+ import Data.Hashable.Lifted (Hashable1 , Hashable2 )
172+ import Data.HashMap.Internal.Array (Array , MArray )
173+ import Data.HashMap.Internal.List (isPermutationBy , unorderedCompare )
174+ import Data.Maybe (isNothing )
175+ import Data.Semigroup (Semigroup (.. ), stimesIdempotentMonoid )
176+ import GHC.Exts (Int (.. ), Int #, TYPE , (==#) )
177+ import GHC.Stack (HasCallStack )
178+ import Prelude hiding (Foldable (.. ), filter , lookup , map ,
179+ pred )
180+ import Text.Read hiding (step )
179181
180182import qualified Data.Data as Data
181183import qualified Data.Foldable as Foldable
@@ -218,7 +220,7 @@ data HashMap k v
218220 -- ^ Invariants:
219221 --
220222 -- * 'Empty' is not a valid sub-node. It can only appear at the root. (INV1)
221- | BitmapIndexed ! Bitmap ! (A. Array (HashMap k v ))
223+ | BitmapIndexed ! Bitmap ! (Array (HashMap k v ))
222224 -- ^ Invariants:
223225 --
224226 -- * Only the lower @maxChildren@ bits of the 'Bitmap' may be set. The
@@ -236,11 +238,11 @@ data HashMap k v
236238 -- compatible with its 'Hash'. (INV6)
237239 -- (TODO: Document this properly (#425))
238240 -- * The 'Hash' of a 'Leaf' node must be the 'hash' of its key. (INV7)
239- | Full ! (A. Array (HashMap k v ))
241+ | Full ! (Array (HashMap k v ))
240242 -- ^ Invariants:
241243 --
242244 -- * The array of a 'Full' node stores exactly 'maxChildren' sub-nodes. (INV8)
243- | Collision ! Hash ! (A. Array (Leaf k v ))
245+ | Collision ! Hash ! (Array (Leaf k v ))
244246 -- ^ Invariants:
245247 --
246248 -- * The location of a 'Leaf' or 'Collision' node in the tree must be
@@ -546,11 +548,11 @@ instance Hashable2 HashMap where
546548 -- hashLeafWithSalt :: Int -> Leaf k v -> Int
547549 hashLeafWithSalt s (L k v) = (s `hk` k) `hv` v
548550
549- -- hashCollisionWithSalt :: Int -> A. Array (Leaf k v) -> Int
551+ -- hashCollisionWithSalt :: Int -> Array (Leaf k v) -> Int
550552 hashCollisionWithSalt s
551553 = List. foldl' H. hashWithSalt s . arrayHashesSorted s
552554
553- -- arrayHashesSorted :: Int -> A. Array (Leaf k v) -> [Int]
555+ -- arrayHashesSorted :: Int -> Array (Leaf k v) -> [Int]
554556 arrayHashesSorted s = List. sort . List. map (hashLeafWithSalt s) . A. toList
555557
556558instance (Hashable k ) => Hashable1 (HashMap k ) where
@@ -573,11 +575,11 @@ instance (Hashable k, Hashable v) => Hashable (HashMap k v) where
573575 hashLeafWithSalt :: Int -> Leaf k v -> Int
574576 hashLeafWithSalt s (L k v) = s `H.hashWithSalt` k `H.hashWithSalt` v
575577
576- hashCollisionWithSalt :: Int -> A. Array (Leaf k v ) -> Int
578+ hashCollisionWithSalt :: Int -> Array (Leaf k v ) -> Int
577579 hashCollisionWithSalt s
578580 = List. foldl' H. hashWithSalt s . arrayHashesSorted s
579581
580- arrayHashesSorted :: Int -> A. Array (Leaf k v ) -> [Int ]
582+ arrayHashesSorted :: Int -> Array (Leaf k v ) -> [Int ]
581583 arrayHashesSorted s = List. sort . List. map (hashLeafWithSalt s) . A. toList
582584
583585-- | Helper to get 'Leaf's and 'Collision's as a list.
@@ -832,7 +834,7 @@ collision h !e1 !e2 =
832834{-# INLINE collision #-}
833835
834836-- | Create a 'BitmapIndexed' or 'Full' node.
835- bitmapIndexedOrFull :: Bitmap -> A. Array (HashMap k v ) -> HashMap k v
837+ bitmapIndexedOrFull :: Bitmap -> Array (HashMap k v ) -> HashMap k v
836838-- The strictness in @ary@ helps achieve a nice code size reduction in
837839-- @unionWith[Key]@ with GHC 9.2.2. See the Core diffs in
838840-- https://github.com/haskell-unordered-containers/unordered-containers/pull/376.
@@ -956,7 +958,7 @@ insertKeyExists !collPos0 !h0 !k0 x0 m0 = go collPos0 h0 k0 x0 m0
956958-- | Replace the ith Leaf with Leaf k v.
957959--
958960-- This does not check that @i@ is within bounds of the array.
959- setAtPosition :: Int -> k -> v -> A. Array (Leaf k v ) -> A. Array (Leaf k v )
961+ setAtPosition :: Int -> k -> v -> Array (Leaf k v ) -> Array (Leaf k v )
960962setAtPosition i k x ary = A. update ary i (L k x)
961963{-# INLINE setAtPosition #-}
962964
@@ -1097,8 +1099,8 @@ insertModifying x f k0 m0 = go h0 k0 0 m0
10971099{-# INLINABLE insertModifying #-}
10981100
10991101-- | Like insertModifying for arrays; used to implement insertModifying
1100- insertModifyingArr :: Eq k => v -> (v -> (# v # )) -> k -> A. Array (Leaf k v )
1101- -> A. Array (Leaf k v )
1102+ insertModifyingArr :: Eq k => v -> (v -> (# v # )) -> k -> Array (Leaf k v )
1103+ -> Array (Leaf k v )
11021104insertModifyingArr x f k0 ary0 = go k0 ary0 0 (A. length ary0)
11031105 where
11041106 go ! k ! ary ! i ! n
@@ -1574,7 +1576,7 @@ isSubmapOfBy comp !m1 !m2 = go 0 m1 m2
15741576{-# INLINABLE isSubmapOfBy #-}
15751577
15761578-- | \(O(\min n m))\) Checks if a bitmap indexed node is a submap of another.
1577- submapBitmapIndexed :: (HashMap k v1 -> HashMap k v2 -> Bool ) -> Bitmap -> A. Array (HashMap k v1 ) -> Bitmap -> A. Array (HashMap k v2 ) -> Bool
1579+ submapBitmapIndexed :: (HashMap k v1 -> HashMap k v2 -> Bool ) -> Bitmap -> Array (HashMap k v1 ) -> Bitmap -> Array (HashMap k v2 ) -> Bool
15781580submapBitmapIndexed comp ! b1 ! ary1 ! b2 ! ary2 = subsetBitmaps && go 0 0 (b1Orb2 .&. negate b1Orb2)
15791581 where
15801582 go :: Int -> Int -> Bitmap -> Bool
@@ -1712,8 +1714,8 @@ unionWithKey f = go 0
17121714{-# INLINE unionWithKey #-}
17131715
17141716-- | Strict in the result of @f@.
1715- unionArrayBy :: (a -> a -> a ) -> Bitmap -> Bitmap -> A. Array a -> A. Array a
1716- -> A. Array a
1717+ unionArrayBy :: (a -> a -> a ) -> Bitmap -> Bitmap -> Array a -> Array a
1718+ -> Array a
17171719-- The manual forcing of @b1@, @b2@, @ary1@ and @ary2@ results in handsome
17181720-- Core size reductions with GHC 9.2.2. See the Core diffs in
17191721-- https://github.com/haskell-unordered-containers/unordered-containers/pull/376.
@@ -1947,7 +1949,7 @@ difference = go_difference 0
19471949-- TODO: This could be faster if we would keep track of which elements of ary2
19481950-- we've already matched. Those could be skipped when we check the following
19491951-- elements of ary1.
1950- differenceCollisions :: Eq k => Hash -> A. Array (Leaf k v1 ) -> HashMap k v1 -> Hash -> A. Array (Leaf k v2 ) -> HashMap k v1
1952+ differenceCollisions :: Eq k => Hash -> Array (Leaf k v1 ) -> HashMap k v1 -> Hash -> Array (Leaf k v2 ) -> HashMap k v1
19511953differenceCollisions ! h1 ! ary1 t1 ! h2 ! ary2
19521954 | h1 == h2 =
19531955 if A. unsafeSameArray ary1 ary2
@@ -2112,7 +2114,7 @@ updateCollision
21122114 => (v -> Maybe v )
21132115 -> Hash
21142116 -> k
2115- -> A. Array (Leaf k v )
2117+ -> Array (Leaf k v )
21162118 -> HashMap k v
21172119 -- ^ The original Collision node which will be re-used if the array is unchanged.
21182120 -> HashMap k v
@@ -2133,7 +2135,7 @@ updateCollision f !h k !ary orig =
21332135-- we've already matched. Those could be skipped when we check the following
21342136-- elements of ary1.
21352137-- TODO: Return tA when the array is unchanged.
2136- differenceWithKey_Collisions :: Eq k => (k -> v -> w -> Maybe v ) -> Word -> A. Array (Leaf k v ) -> HashMap k v -> Word -> A. Array (Leaf k w ) -> HashMap k v
2138+ differenceWithKey_Collisions :: Eq k => (k -> v -> w -> Maybe v ) -> Word -> Array (Leaf k v ) -> HashMap k v -> Word -> Array (Leaf k w ) -> HashMap k v
21372139differenceWithKey_Collisions f ! hA ! aryA ! tA ! hB ! aryB
21382140 | hA == hB =
21392141 let f' l@ (L kA vA) =
@@ -2234,8 +2236,8 @@ intersectionArrayBy ::
22342236 ) ->
22352237 Bitmap ->
22362238 Bitmap ->
2237- A. Array (HashMap k v1 ) ->
2238- A. Array (HashMap k v2 ) ->
2239+ Array (HashMap k v1 ) ->
2240+ Array (HashMap k v2 ) ->
22392241 HashMap k v3
22402242intersectionArrayBy f ! b1 ! b2 ! ary1 ! ary2
22412243 | b1 .&. b2 == 0 = Empty
@@ -2272,7 +2274,7 @@ intersectionArrayBy f !b1 !b2 !ary1 !ary2
22722274 bIntersect = b1 .&. b2
22732275{-# INLINE intersectionArrayBy #-}
22742276
2275- intersectionCollisions :: Eq k => (k -> v1 -> v2 -> (# v3 # )) -> Hash -> Hash -> A. Array (Leaf k v1 ) -> A. Array (Leaf k v2 ) -> HashMap k v3
2277+ intersectionCollisions :: Eq k => (k -> v1 -> v2 -> (# v3 # )) -> Hash -> Hash -> Array (Leaf k v1 ) -> Array (Leaf k v2 ) -> HashMap k v3
22762278intersectionCollisions f h1 h2 ary1 ary2
22772279 | h1 == h2 = runST $ do
22782280 let ! n2 = A. length ary2
@@ -2306,7 +2308,7 @@ intersectionCollisions f h1 h2 ary1 ary2
23062308-- undefined 2 1 4
23072309-- @
23082310-- We don't actually need to write undefined, we just have to make sure that the next search starts 1 after the current one.
2309- searchSwap :: Eq k => A. MArray s (Leaf k v ) -> Int -> k -> Int -> ST s (Maybe (Leaf k v ))
2311+ searchSwap :: Eq k => MArray s (Leaf k v ) -> Int -> k -> Int -> ST s (Maybe (Leaf k v ))
23102312searchSwap mary n toFind start = go start toFind start
23112313 where
23122314 go i0 k i
@@ -2382,7 +2384,7 @@ disjointSubtrees s a (Leaf hB (L kB _)) =
23822384disjointSubtrees s a b@ Collision {} = disjointSubtrees s b a
23832385{-# INLINABLE disjointSubtrees #-}
23842386
2385- disjointArrays :: Eq k => Shift -> Bitmap -> A. Array (HashMap k a ) -> Bitmap -> A. Array (HashMap k b ) -> Bool
2387+ disjointArrays :: Eq k => Shift -> Bitmap -> Array (HashMap k a ) -> Bitmap -> Array (HashMap k b ) -> Bool
23862388disjointArrays ! s ! bmA ! aryA ! bmB ! aryB = go (bmA .&. bmB)
23872389 where
23882390 go 0 = True
@@ -2400,7 +2402,7 @@ disjointArrays !s !bmA !aryA !bmB !aryB = go (bmA .&. bmB)
24002402-- TODO: GHC 9.12.2 inlines disjointCollisions into `disjoint @Int`.
24012403-- How do you prevent this while preserving specialization?
24022404-- https://stackoverflow.com/questions/79838305/ensuring-specialization-while-preventing-inlining
2403- disjointCollisions :: Eq k => Hash -> A. Array (Leaf k a ) -> Hash -> A. Array (Leaf k b ) -> Bool
2405+ disjointCollisions :: Eq k => Hash -> Array (Leaf k a ) -> Hash -> Array (Leaf k b ) -> Bool
24042406disjointCollisions ! hA ! aryA ! hB ! aryB
24052407 | hA == hB = A. all predicate aryA
24062408 | otherwise = True
@@ -2566,7 +2568,7 @@ filterMapAux onLeaf onColl = go
25662568 mary <- A. new_ n
25672569 step ary0 mary b0 0 0 1 n
25682570 where
2569- step :: A. Array (HashMap k v1 ) -> A. MArray s (HashMap k v2 )
2571+ step :: Array (HashMap k v1 ) -> MArray s (HashMap k v2 )
25702572 -> Bitmap -> Int -> Int -> Bitmap -> Int
25712573 -> ST s (HashMap k v2 )
25722574 step ! ary ! mary ! b i ! j ! bi n
@@ -2598,7 +2600,7 @@ filterMapAux onLeaf onColl = go
25982600 mary <- A. new_ n
25992601 step ary0 mary 0 0 n
26002602 where
2601- step :: A. Array (Leaf k v1 ) -> A. MArray s (Leaf k v2 )
2603+ step :: Array (Leaf k v1 ) -> MArray s (Leaf k v2 )
26022604 -> Int -> Int -> Int
26032605 -> ST s (HashMap k v2 )
26042606 step ! ary ! mary i ! j n
@@ -2731,11 +2733,11 @@ lookupInArrayCont ::
27312733#else
27322734 forall r k v.
27332735#endif
2734- Eq k => ((# # ) -> r) -> (v -> Int -> r) -> k -> A. Array (Leaf k v) -> r
2736+ Eq k => ((# # ) -> r) -> (v -> Int -> r) -> k -> Array (Leaf k v) -> r
27352737lookupInArrayCont absent present k0 ary0 =
27362738 lookupInArrayCont_ k0 ary0 0 (A. length ary0)
27372739 where
2738- lookupInArrayCont_ :: Eq k => k -> A. Array (Leaf k v ) -> Int -> Int -> r
2740+ lookupInArrayCont_ :: Eq k => k -> Array (Leaf k v ) -> Int -> Int -> r
27392741 lookupInArrayCont_ ! k ! ary ! i ! n
27402742 | i >= n = absent (# # )
27412743 | otherwise = case A. index# ary i of
@@ -2746,7 +2748,7 @@ lookupInArrayCont absent present k0 ary0 =
27462748
27472749-- | \(O(n)\) Lookup the value associated with the given key in this
27482750-- array. Returns 'Nothing' if the key wasn't found.
2749- indexOf :: Eq k => k -> A. Array (Leaf k v ) -> Maybe Int
2751+ indexOf :: Eq k => k -> Array (Leaf k v ) -> Maybe Int
27502752indexOf k0 ary0 = go k0 ary0 0 (A. length ary0)
27512753 where
27522754 go ! k ! ary ! i ! n
@@ -2757,7 +2759,7 @@ indexOf k0 ary0 = go k0 ary0 0 (A.length ary0)
27572759 | otherwise -> go k ary (i+ 1 ) n
27582760{-# INLINABLE indexOf #-}
27592761
2760- updateWith# :: Eq k => (v -> (# v # )) -> k -> A. Array (Leaf k v ) -> A. Array (Leaf k v )
2762+ updateWith# :: Eq k => (v -> (# v # )) -> k -> Array (Leaf k v ) -> Array (Leaf k v )
27612763updateWith# f k0 ary0 = go k0 ary0 0 (A. length ary0)
27622764 where
27632765 go ! k ! ary ! i ! n
@@ -2770,13 +2772,13 @@ updateWith# f k0 ary0 = go k0 ary0 0 (A.length ary0)
27702772 | otherwise -> go k ary (i+ 1 ) n
27712773{-# INLINABLE updateWith# #-}
27722774
2773- updateOrSnocWith :: Eq k => (v -> v -> (# v # )) -> k -> v -> A. Array (Leaf k v )
2774- -> A. Array (Leaf k v )
2775+ updateOrSnocWith :: Eq k => (v -> v -> (# v # )) -> k -> v -> Array (Leaf k v )
2776+ -> Array (Leaf k v )
27752777updateOrSnocWith f = updateOrSnocWithKey (const f)
27762778{-# INLINABLE updateOrSnocWith #-}
27772779
2778- updateOrSnocWithKey :: Eq k => (k -> v -> v -> (# v # )) -> k -> v -> A. Array (Leaf k v )
2779- -> A. Array (Leaf k v )
2780+ updateOrSnocWithKey :: Eq k => (k -> v -> v -> (# v # )) -> k -> v -> Array (Leaf k v )
2781+ -> Array (Leaf k v )
27802782updateOrSnocWithKey f k0 v0 ary0 = go k0 v0 ary0 0 (A. length ary0)
27812783 where
27822784 go ! k v ! ary ! i ! n
@@ -2789,7 +2791,7 @@ updateOrSnocWithKey f k0 v0 ary0 = go k0 v0 ary0 0 (A.length ary0)
27892791 | otherwise -> go k v ary (i+ 1 ) n
27902792{-# INLINABLE updateOrSnocWithKey #-}
27912793
2792- updateOrConcatWithKey :: Eq k => (k -> v -> v -> (# v # )) -> A. Array (Leaf k v ) -> A. Array (Leaf k v ) -> A. Array (Leaf k v )
2794+ updateOrConcatWithKey :: Eq k => (k -> v -> v -> (# v # )) -> Array (Leaf k v ) -> Array (Leaf k v ) -> Array (Leaf k v )
27932795updateOrConcatWithKey f ary1 ary2 = A. run $ do
27942796 -- TODO: instead of mapping and then folding, should we traverse?
27952797 -- We'll have to be careful to avoid allocating pairs or similar.
@@ -2822,7 +2824,7 @@ updateOrConcatWithKey f ary1 ary2 = A.run $ do
28222824{-# INLINABLE updateOrConcatWithKey #-}
28232825
28242826-- | \(O(n*m)\) Check if the first array is a subset of the second array.
2825- subsetArray :: Eq k => (v1 -> v2 -> Bool ) -> A. Array (Leaf k v1 ) -> A. Array (Leaf k v2 ) -> Bool
2827+ subsetArray :: Eq k => (v1 -> v2 -> Bool ) -> Array (Leaf k v1 ) -> Array (Leaf k v2 ) -> Bool
28262828subsetArray cmpV ary1 ary2 = A. length ary1 <= A. length ary2 && A. all inAry2 ary1
28272829 where
28282830 inAry2 (L k1 v1) = lookupInArrayCont (\ _ -> False ) (\ v2 _ -> cmpV v1 v2) k1 ary2
@@ -2832,28 +2834,28 @@ subsetArray cmpV ary1 ary2 = A.length ary1 <= A.length ary2 && A.all inAry2 ary1
28322834-- Manually unrolled loops
28332835
28342836-- | \(O(n)\) Update the element at the given position in this array.
2835- updateFullArray :: A. Array e -> Int -> e -> A. Array e
2837+ updateFullArray :: Array e -> Int -> e -> Array e
28362838updateFullArray ary idx b = runST (updateFullArrayM ary idx b)
28372839{-# INLINE updateFullArray #-}
28382840
28392841-- | \(O(n)\) Update the element at the given position in this array.
2840- updateFullArrayM :: A. Array e -> Int -> e -> ST s (A. Array e )
2842+ updateFullArrayM :: Array e -> Int -> e -> ST s (Array e )
28412843updateFullArrayM ary idx b = do
28422844 mary <- clone ary
28432845 A. write mary idx b
28442846 A. unsafeFreeze mary
28452847{-# INLINE updateFullArrayM #-}
28462848
28472849-- | \(O(n)\) Update the element at the given position in this array, by applying a function to it.
2848- updateFullArrayWith' :: A. Array e -> Int -> (e -> e ) -> A. Array e
2850+ updateFullArrayWith' :: Array e -> Int -> (e -> e ) -> Array e
28492851updateFullArrayWith' ary idx f =
28502852 case A. index# ary idx of
28512853 (# x # ) -> updateFullArray ary idx $! f x
28522854{-# INLINE updateFullArrayWith' #-}
28532855
28542856-- | Unsafely clone an array of (2^bitsPerSubkey) elements. The length of the input
28552857-- array is not checked.
2856- clone :: A. Array e -> ST s (A. MArray s e )
2858+ clone :: Array e -> ST s (MArray s e )
28572859clone ary =
28582860 A. thaw ary 0 (2 ^ bitsPerSubkey)
28592861
0 commit comments