@@ -1600,12 +1600,35 @@ mapMaybeWithKey f = filterMapAux onLeaf onColl
16001600 | otherwise = Nothing
16011601{-# INLINE mapMaybeWithKey #-}
16021602
1603+ -- | /O(n)/ Transform this map by applying a function to every value
1604+ -- and retaining only some of them.
1605+ -- Returns a tuple with the size of the result hashmap and the the hashmap
1606+ -- itself.
1607+ mapMaybeWithKeyInternal
1608+ :: (k -> v1 -> Maybe v2 )
1609+ -> HashMap k v1
1610+ -> (Int , HashMap k v2 )
1611+ mapMaybeWithKeyInternal f = filterMapAuxInternal onLeaf onColl
1612+ where onLeaf (Leaf h (L k v)) | Just v' <- f k v = Just (Leaf h (L k v'))
1613+ onLeaf _ = Nothing
1614+
1615+ onColl (L k v) | Just v' <- f k v = Just (L k v')
1616+ | otherwise = Nothing
1617+ {-# INLINE mapMaybeWithKeyInternal #-}
1618+
16031619-- | /O(n)/ Transform this map by applying a function to every value
16041620-- and retaining only some of them.
16051621mapMaybe :: (v1 -> Maybe v2 ) -> HashMap k v1 -> HashMap k v2
16061622mapMaybe f = mapMaybeWithKey (const f)
16071623{-# INLINE mapMaybe #-}
16081624
1625+ -- | /O(n)/ Transform this map by applying a function to every value
1626+ -- and retaining only some of them.
1627+ -- Returns a tuple with the result hashmap's size and the hasmap itself.
1628+ mapMaybeInternal :: (v1 -> Maybe v2 ) -> HashMap k v1 -> (Int , HashMap k v2 )
1629+ mapMaybeInternal f = mapMaybeWithKeyInternal (const f)
1630+ {-# INLINE mapMaybeInternal #-}
1631+
16091632-- | /O(n)/ Filter this map by retaining only elements satisfying a
16101633-- predicate.
16111634filterWithKey :: forall k v . (k -> v -> Bool ) -> HashMap k v -> HashMap k v
@@ -1617,6 +1640,17 @@ filterWithKey pred = filterMapAux onLeaf onColl
16171640 onColl _ = Nothing
16181641{-# INLINE filterWithKey #-}
16191642
1643+ -- | /O(n)/ Filter this map by retaining only elements satisfying a
1644+ -- predicate.
1645+ -- Returns a tuple with the result hashmap's size and the hashmap itself.
1646+ filterWithKeyInternal :: forall k v . (k -> v -> Bool ) -> HashMap k v -> (Int , HashMap k v )
1647+ filterWithKeyInternal pred = filterMapAuxInternal onLeaf onColl
1648+ where onLeaf t@ (Leaf _ (L k v)) | pred k v = Just t
1649+ onLeaf _ = Nothing
1650+
1651+ onColl el@ (L k v) | pred k v = Just el
1652+ onColl _ = Nothing
1653+ {-# INLINE filterWithKeyInternal #-}
16201654
16211655-- | Common implementation for 'filterWithKey' and 'mapMaybeWithKey',
16221656-- allowing the former to former to reuse terms.
@@ -1687,12 +1721,91 @@ filterMapAux onLeaf onColl = go
16871721 | otherwise = step ary mary (i+ 1 ) j n
16881722{-# INLINE filterMapAux #-}
16891723
1724+ -- | Common implementation for 'filterWithKey' and 'mapMaybeWithKey',
1725+ -- allowing the former to former to reuse terms.
1726+ -- Returns the change in the hashmap's size, and the hashmap itself.
1727+ filterMapAuxInternal :: forall k v1 v2
1728+ . (HashMap k v1 -> Maybe (HashMap k v2 ))
1729+ -> (Leaf k v1 -> Maybe (Leaf k v2 ))
1730+ -> HashMap k v1
1731+ -> (Int , HashMap k v2 )
1732+ filterMapAuxInternal onLeaf onColl = go 0
1733+ where
1734+ go ! sz Empty = (sz, Empty )
1735+ go ! sz t@ Leaf {}
1736+ | Just t' <- onLeaf t = (sz + 1 , t')
1737+ | otherwise = (sz, Empty )
1738+ go ! sz (BitmapIndexed b ary) = filterA sz ary b
1739+ go ! sz (Full ary) = filterA sz ary fullNodeMask
1740+ go ! sz (Collision h ary) = filterC sz ary h
1741+
1742+ filterA size ary0 b0 =
1743+ let ! n = A. length ary0
1744+ in runST $ do
1745+ mary <- A. new_ n
1746+ step ary0 mary b0 0 0 1 n size
1747+ where
1748+ step :: A. Array (HashMap k v1 ) -> A. MArray s (HashMap k v2 )
1749+ -> Bitmap -> Int -> Int -> Bitmap -> Int -> Int
1750+ -> ST s (Int , HashMap k v2 )
1751+ step ! ary ! mary ! b i ! j ! bi n ! sz
1752+ | i >= n = case j of
1753+ 0 -> return (sz, Empty )
1754+ 1 -> do
1755+ ch <- A. read mary 0
1756+ case ch of
1757+ t | isLeafOrCollision t -> return (sz, t)
1758+ _ -> (sz,) . BitmapIndexed b <$> trim mary 1
1759+ _ -> do
1760+ ary2 <- trim mary j
1761+ return $! (sz,) (if j == maxChildren
1762+ then Full ary2
1763+ else BitmapIndexed b ary2)
1764+ | bi .&. b == 0 = step ary mary b i j (bi `unsafeShiftL` 1 ) n sz
1765+ | otherwise = case go sz (A. index ary i) of
1766+ (dsz, Empty ) -> step ary mary (b .&. complement bi) (i+ 1 ) j
1767+ (bi `unsafeShiftL` 1 ) n dsz
1768+ (dsz, t) -> do A. write mary j t
1769+ step ary mary b (i+ 1 ) (j+ 1 )
1770+ (bi `unsafeShiftL` 1 ) n dsz
1771+
1772+ filterC size ary0 h =
1773+ let ! n = A. length ary0
1774+ in runST $ do
1775+ mary <- A. new_ n
1776+ step ary0 mary 0 0 n size
1777+ where
1778+ step :: A. Array (Leaf k v1 ) -> A. MArray s (Leaf k v2 )
1779+ -> Int -> Int -> Int -> Int
1780+ -> ST s (Int , HashMap k v2 )
1781+ step ! ary ! mary i ! j n ! sz
1782+ | i >= n = case j of
1783+ 0 -> return (sz, Empty )
1784+ 1 -> do l <- A. read mary 0
1785+ return $! (sz, Leaf h l)
1786+ _ | i == j -> do ary2 <- A. unsafeFreeze mary
1787+ return $! (sz, Collision h ary2)
1788+ | otherwise -> do ary2 <- trim mary j
1789+ return $! (sz, Collision h ary2)
1790+ | Just el <- onColl (A. index ary i)
1791+ = A. write mary j el >> step ary mary (i+ 1 ) (j+ 1 ) n (sz + 1 )
1792+ | otherwise = step ary mary (i+ 1 ) j n sz
1793+ {-# INLINE filterMapAuxInternal #-}
1794+
16901795-- | /O(n)/ Filter this map by retaining only elements which values
16911796-- satisfy a predicate.
16921797filter :: (v -> Bool ) -> HashMap k v -> HashMap k v
16931798filter p = filterWithKey (\ _ v -> p v)
16941799{-# INLINE filter #-}
16951800
1801+ -- | /O(n)/ Filter this map by retaining only elements which values
1802+ -- satisfy a predicate.
1803+ -- Returns a tuple with the new size of the result hashmap, and the hashmap
1804+ -- itself.
1805+ filterInternal :: (v -> Bool ) -> HashMap k v -> (Int , HashMap k v )
1806+ filterInternal p = filterWithKeyInternal (\ _ v -> p v)
1807+ {-# INLINE filterInternal #-}
1808+
16961809------------------------------------------------------------------------
16971810-- * Conversions
16981811
0 commit comments