@@ -107,6 +107,8 @@ module Data.HashMap.Base
107
107
, insertModifying
108
108
, ptrEq
109
109
, adjust #
110
+ , unionWithKey #
111
+ , unsafeInsertWith
110
112
) where
111
113
112
114
#if __GLASGOW_HASKELL__ < 710
@@ -650,7 +652,7 @@ insert' h0 k0 v0 m0 = go h0 k0 v0 0 m0
650
652
else Full (update16 ary i st')
651
653
where i = index h s
652
654
go h k x s t@ (Collision hy v)
653
- | h == hy = Collision h (updateOrSnocWith const k x v)
655
+ | h == hy = Collision h (updateOrSnocWith ( \ v1 _ -> ( # v1 # )) k x v)
654
656
| otherwise = go h k x s $ BitmapIndexed (mask hy s) (A. singleton t)
655
657
{-# INLINABLE insert' #-}
656
658
@@ -773,7 +775,7 @@ unsafeInsert k0 v0 m0 = runST (go h0 k0 v0 0 m0)
773
775
return t
774
776
where i = index h s
775
777
go h k x s t@ (Collision hy v)
776
- | h == hy = return $! Collision h (updateOrSnocWith const k x v)
778
+ | h == hy = return $! Collision h (updateOrSnocWith ( \ v1 _ -> ( # v1 # )) k x v)
777
779
| otherwise = go h k x s $ BitmapIndexed (mask hy s) (A. singleton t)
778
780
{-# INLINABLE unsafeInsert #-}
779
781
@@ -882,7 +884,7 @@ insertModifyingArr x f k0 ary0 = go k0 ary0 0 (A.length ary0)
882
884
883
885
-- | In-place update version of insertWith
884
886
unsafeInsertWith :: forall k v . (Eq k , Hashable k )
885
- => (v -> v -> v ) -> k -> v -> HashMap k v
887
+ => (v -> v -> ( # v # ) ) -> k -> v -> HashMap k v
886
888
-> HashMap k v
887
889
unsafeInsertWith f k0 v0 m0 = runST (go h0 k0 v0 0 m0)
888
890
where
@@ -891,7 +893,7 @@ unsafeInsertWith f k0 v0 m0 = runST (go h0 k0 v0 0 m0)
891
893
go ! h ! k x ! _ Empty = return $! Leaf h (L k x)
892
894
go h k x s (Leaf hy l@ (L ky y))
893
895
| hy == h = if ky == k
894
- then return $! Leaf h (L k (f x y) )
896
+ then case f x y of ( # v # ) -> return $! Leaf h (L k v )
895
897
else return $! collision h l (L k x)
896
898
| otherwise = two s h k x hy ky y
897
899
go h k x s t@ (BitmapIndexed b ary)
@@ -1256,22 +1258,27 @@ unionWith f = unionWithKey (const f)
1256
1258
-- result.
1257
1259
unionWithKey :: (Eq k , Hashable k ) => (k -> v -> v -> v ) -> HashMap k v -> HashMap k v
1258
1260
-> HashMap k v
1259
- unionWithKey f = go 0
1261
+ unionWithKey f m = unionWithKey# (\ k v1 v2 -> (# f k v1 v2 # )) m
1262
+ {-# INLINE unionWithKey #-}
1263
+
1264
+ unionWithKey# :: (Eq k , Hashable k ) => (k -> v -> v -> (# v # )) -> HashMap k v -> HashMap k v
1265
+ -> HashMap k v
1266
+ unionWithKey# f = go 0
1260
1267
where
1261
1268
-- empty vs. anything
1262
1269
go ! _ t1 Empty = t1
1263
1270
go _ Empty t2 = t2
1264
1271
-- leaf vs. leaf
1265
1272
go s t1@ (Leaf h1 l1@ (L k1 v1)) t2@ (Leaf h2 l2@ (L k2 v2))
1266
1273
| h1 == h2 = if k1 == k2
1267
- then Leaf h1 ( L k1 ( f k1 v1 v2) )
1274
+ then case f k1 v1 v2 of ( # v # ) -> Leaf h1 ( L k1 v )
1268
1275
else collision h1 l1 l2
1269
1276
| otherwise = goDifferentHash s h1 h2 t1 t2
1270
1277
go s t1@ (Leaf h1 (L k1 v1)) t2@ (Collision h2 ls2)
1271
1278
| h1 == h2 = Collision h1 (updateOrSnocWithKey f k1 v1 ls2)
1272
1279
| otherwise = goDifferentHash s h1 h2 t1 t2
1273
1280
go s t1@ (Collision h1 ls1) t2@ (Leaf h2 (L k2 v2))
1274
- | h1 == h2 = Collision h1 (updateOrSnocWithKey (flip . f ) k2 v2 ls1)
1281
+ | h1 == h2 = Collision h1 (updateOrSnocWithKey (\ q w x -> f q x w ) k2 v2 ls1)
1275
1282
| otherwise = goDifferentHash s h1 h2 t1 t2
1276
1283
go s t1@ (Collision h1 ls1) t2@ (Collision h2 ls2)
1277
1284
| h1 == h2 = Collision h1 (updateOrConcatWithKey f ls1 ls2)
@@ -1336,7 +1343,8 @@ unionWithKey f = go 0
1336
1343
where
1337
1344
m1 = mask h1 s
1338
1345
m2 = mask h2 s
1339
- {-# INLINE unionWithKey #-}
1346
+ {-# INLINE unionWithKey# #-}
1347
+
1340
1348
1341
1349
-- | Strict in the result of @f@.
1342
1350
unionArrayBy :: (a -> a -> a ) -> Bitmap -> Bitmap -> A. Array a -> A. Array a
@@ -1667,7 +1675,7 @@ fromList = L.foldl' (\ m (k, v) -> unsafeInsert k v m) empty
1667
1675
-- | /O(n*log n)/ Construct a map from a list of elements. Uses
1668
1676
-- the provided function to merge duplicate entries.
1669
1677
fromListWith :: (Eq k , Hashable k ) => (v -> v -> v ) -> [(k , v )] -> HashMap k v
1670
- fromListWith f = L. foldl' (\ m (k, v) -> unsafeInsertWith f k v m) empty
1678
+ fromListWith f = L. foldl' (\ m (k, v) -> unsafeInsertWith ( \ x y -> ( # f x y # )) k v m) empty
1671
1679
{-# INLINE fromListWith #-}
1672
1680
1673
1681
------------------------------------------------------------------------
@@ -1719,12 +1727,12 @@ updateWith# f k0 ary0 = go k0 ary0 0 (A.length ary0)
1719
1727
| otherwise -> go k ary (i+ 1 ) n
1720
1728
{-# INLINABLE updateWith# #-}
1721
1729
1722
- updateOrSnocWith :: Eq k => (v -> v -> v ) -> k -> v -> A. Array (Leaf k v )
1730
+ updateOrSnocWith :: Eq k => (v -> v -> ( # v # ) ) -> k -> v -> A. Array (Leaf k v )
1723
1731
-> A. Array (Leaf k v )
1724
1732
updateOrSnocWith f = updateOrSnocWithKey (const f)
1725
1733
{-# INLINABLE updateOrSnocWith #-}
1726
1734
1727
- updateOrSnocWithKey :: Eq k => (k -> v -> v -> v ) -> k -> v -> A. Array (Leaf k v )
1735
+ updateOrSnocWithKey :: Eq k => (k -> v -> v -> ( # v # ) ) -> k -> v -> A. Array (Leaf k v )
1728
1736
-> A. Array (Leaf k v )
1729
1737
updateOrSnocWithKey f k0 v0 ary0 = go k0 v0 ary0 0 (A. length ary0)
1730
1738
where
@@ -1736,15 +1744,15 @@ updateOrSnocWithKey f k0 v0 ary0 = go k0 v0 ary0 0 (A.length ary0)
1736
1744
A. write mary n (L k v)
1737
1745
return mary
1738
1746
| otherwise = case A. index ary i of
1739
- (L kx y) | k == kx -> A. update ary i (L k (f k v y) )
1747
+ (L kx y) | k == kx -> case f k v y of ( # y' # ) -> A. update ary i (L k y' )
1740
1748
| otherwise -> go k v ary (i+ 1 ) n
1741
1749
{-# INLINABLE updateOrSnocWithKey #-}
1742
1750
1743
- updateOrConcatWith :: Eq k => (v -> v -> v ) -> A. Array (Leaf k v ) -> A. Array (Leaf k v ) -> A. Array (Leaf k v )
1751
+ updateOrConcatWith :: Eq k => (v -> v -> ( # v # ) ) -> A. Array (Leaf k v ) -> A. Array (Leaf k v ) -> A. Array (Leaf k v )
1744
1752
updateOrConcatWith f = updateOrConcatWithKey (const f)
1745
1753
{-# INLINABLE updateOrConcatWith #-}
1746
1754
1747
- updateOrConcatWithKey :: Eq k => (k -> v -> v -> v ) -> A. Array (Leaf k v ) -> A. Array (Leaf k v ) -> A. Array (Leaf k v )
1755
+ updateOrConcatWithKey :: Eq k => (k -> v -> v -> ( # v # ) ) -> A. Array (Leaf k v ) -> A. Array (Leaf k v ) -> A. Array (Leaf k v )
1748
1756
updateOrConcatWithKey f ary1 ary2 = A. run $ do
1749
1757
-- first: look up the position of each element of ary2 in ary1
1750
1758
let indices = A. map (\ (L k _) -> indexOf k ary1) ary2
@@ -1763,7 +1771,7 @@ updateOrConcatWithKey f ary1 ary2 = A.run $ do
1763
1771
Just i1 -> do -- key occurs in both arrays, store combination in position i1
1764
1772
L k v1 <- A. indexM ary1 i1
1765
1773
L _ v2 <- A. indexM ary2 i2
1766
- A. write mary i1 (L k (f k v1 v2) )
1774
+ case f k v1 v2 of ( # v' # ) -> A. write mary i1 (L k v' )
1767
1775
go iEnd (i2+ 1 )
1768
1776
Nothing -> do -- key is only in ary2, append to end
1769
1777
A. write mary iEnd =<< A. indexM ary2 i2
0 commit comments