@@ -134,6 +134,7 @@ module Data.HashMap.Internal
134
134
, equalKeys1
135
135
, lookupRecordCollision
136
136
, LookupRes (.. )
137
+ , lookupResToMaybe
137
138
, insert'
138
139
, delete'
139
140
, lookup'
@@ -655,6 +656,11 @@ lookup' h k m = case lookupRecordCollision# h k m of
655
656
-- If a collision did not occur then it will have the Int value (-1).
656
657
data LookupRes a = Absent | Present a ! Int
657
658
659
+ lookupResToMaybe :: LookupRes a -> Maybe a
660
+ lookupResToMaybe Absent = Nothing
661
+ lookupResToMaybe (Present x _) = Just x
662
+ {-# INLINE lookupResToMaybe #-}
663
+
658
664
-- Internal helper for lookup. This version takes the precomputed hash so
659
665
-- that functions that make multiple calls to lookup and related functions
660
666
-- (insert, delete) only need to calculate the hash once.
@@ -1265,11 +1271,19 @@ update f = alter (>>= f)
1265
1271
-- 'lookup' k ('alter' f k m) = f ('lookup' k m)
1266
1272
-- @
1267
1273
alter :: (Eq k , Hashable k ) => (Maybe v -> Maybe v ) -> k -> HashMap k v -> HashMap k v
1268
- -- TODO(m-renaud): Consider using specialized insert and delete for alter.
1269
1274
alter f k m =
1270
- case f (lookup k m) of
1271
- Nothing -> delete k m
1272
- Just v -> insert k v m
1275
+ let ! h = hash k
1276
+ ! lookupRes = lookupRecordCollision h k m
1277
+ in case f (lookupResToMaybe lookupRes) of
1278
+ Nothing -> case lookupRes of
1279
+ Absent -> m
1280
+ Present _ collPos -> deleteKeyExists collPos h k m
1281
+ Just v' -> case lookupRes of
1282
+ Absent -> insertNewKey h k v' m
1283
+ Present v collPos ->
1284
+ if v `ptrEq` v'
1285
+ then m
1286
+ else insertKeyExists collPos h k v' m
1273
1287
{-# INLINABLE alter #-}
1274
1288
1275
1289
-- | \(O(\log n)\) The expression @('alterF' f k map)@ alters the value @x@ at
0 commit comments