@@ -1600,12 +1600,35 @@ mapMaybeWithKey f = filterMapAux onLeaf onColl
1600
1600
| otherwise = Nothing
1601
1601
{-# INLINE mapMaybeWithKey #-}
1602
1602
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
+
1603
1619
-- | /O(n)/ Transform this map by applying a function to every value
1604
1620
-- and retaining only some of them.
1605
1621
mapMaybe :: (v1 -> Maybe v2) -> HashMap k v1 -> HashMap k v2
1606
1622
mapMaybe f = mapMaybeWithKey (const f)
1607
1623
{-# INLINE mapMaybe #-}
1608
1624
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
+
1609
1632
-- | /O(n)/ Filter this map by retaining only elements satisfying a
1610
1633
-- predicate.
1611
1634
filterWithKey :: forall k v. (k -> v -> Bool) -> HashMap k v -> HashMap k v
@@ -1617,6 +1640,17 @@ filterWithKey pred = filterMapAux onLeaf onColl
1617
1640
onColl _ = Nothing
1618
1641
{-# INLINE filterWithKey #-}
1619
1642
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 #-}
1620
1654
1621
1655
-- | Common implementation for 'filterWithKey' and 'mapMaybeWithKey',
1622
1656
-- allowing the former to former to reuse terms.
@@ -1687,12 +1721,91 @@ filterMapAux onLeaf onColl = go
1687
1721
| otherwise = step ary mary (i+1) j n
1688
1722
{-# INLINE filterMapAux #-}
1689
1723
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
+
1690
1795
-- | /O(n)/ Filter this map by retaining only elements which values
1691
1796
-- satisfy a predicate.
1692
1797
filter :: (v -> Bool) -> HashMap k v -> HashMap k v
1693
1798
filter p = filterWithKey (\_ v -> p v)
1694
1799
{-# INLINE filter #-}
1695
1800
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
+
1696
1809
------------------------------------------------------------------------
1697
1810
-- * Conversions
1698
1811
0 commit comments