@@ -712,7 +712,10 @@ insertWith f k0 v0 m0 = go h0 k0 v0 0 m0
712
712
-- | /O(log n)/ Associate the value with the key in this map. If
713
713
-- this map previously contained a mapping for the key, the old value
714
714
-- is replaced by the result of applying the given function to the new
715
- -- and old value. Example:
715
+ -- and old value. Returns a tuple where the first component is the
716
+ -- difference in size between the old and new hashmaps, and the second
717
+ -- is the new hashmap.
718
+ -- Example:
716
719
--
717
720
-- > insertWithInternal f k v map
718
721
-- > where f new old = new + old
@@ -789,6 +792,48 @@ unsafeInsertWith f k0 v0 m0 = runST (go h0 k0 v0 0 m0)
789
792
| otherwise = go h k x s $ BitmapIndexed (mask hy s) (A. singleton t)
790
793
{-# INLINABLE unsafeInsertWith #-}
791
794
795
+ -- | In-place update version of insertWithInternal
796
+ unsafeInsertWithInternal :: forall k v . (Eq k , Hashable k )
797
+ => (v -> v -> v ) -> k -> v -> HashMap k v
798
+ -> (Int , HashMap k v )
799
+ unsafeInsertWithInternal f k0 v0 m0 = runST (go h0 k0 v0 0 m0)
800
+ where
801
+ h0 = hash k0
802
+ go :: Hash -> k -> v -> Shift -> HashMap k v -> ST s (Int , HashMap k v )
803
+ go ! h ! k x ! _ Empty = return $! (1 , Leaf h (L k x))
804
+ go h k x s (Leaf hy l@ (L ky y))
805
+ | hy == h = if ky == k
806
+ then return $! (0 , Leaf h (L k (f x y)))
807
+ else return $! (1 , collision h l (L k x))
808
+ | otherwise = do
809
+ twoHm <- two s h k x hy ky y
810
+ return $! (1 , twoHm)
811
+ go h k x s t@ (BitmapIndexed b ary)
812
+ | b .&. m == 0 = do
813
+ ary' <- A. insertM ary i $! Leaf h (L k x)
814
+ return $! (1 , bitmapIndexedOrFull (b .|. m) ary')
815
+ | otherwise = do
816
+ st <- A. indexM ary i
817
+ (sz, st') <- go h k x (s+ bitsPerSubkey) st
818
+ A. unsafeUpdateM ary i st'
819
+ return (sz, t)
820
+ where m = mask h s
821
+ i = sparseIndex b m
822
+ go h k x s t@ (Full ary) = do
823
+ st <- A. indexM ary i
824
+ (sz, st') <- go h k x (s+ bitsPerSubkey) st
825
+ A. unsafeUpdateM ary i st'
826
+ return (sz, t)
827
+ where i = index h s
828
+ go h k x s t@ (Collision hy v)
829
+ | h == hy =
830
+ let ! start = A. length v
831
+ ! newV = updateOrSnocWith const k x v
832
+ ! end = A. length newV
833
+ in return $! (end - start, Collision h newV)
834
+ | otherwise = go h k x s $ BitmapIndexed (mask hy s) (A. singleton t)
835
+ {-# INLINABLE unsafeInsertWithInternal #-}
836
+
792
837
-- | /O(log n)/ Remove the mapping for the specified key from this map
793
838
-- if present.
794
839
delete :: (Eq k , Hashable k ) => k -> HashMap k v -> HashMap k v
0 commit comments