Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 50 additions & 12 deletions containers/src/Data/IntMap/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1209,6 +1209,7 @@ alterF f k m = (<$> f mv) $ \fres ->
unions :: Foldable f => f (IntMap a) -> IntMap a
unions xs
= Foldable.foldl' union empty xs
{-# INLINE unions #-} -- Inline for list fusion

-- | The union of a list of maps, with a combining operation.
--
Expand All @@ -1218,6 +1219,7 @@ unions xs
unionsWith :: Foldable f => (a->a->a) -> f (IntMap a) -> IntMap a
unionsWith f ts
= Foldable.foldl' (unionWith f) empty ts
{-# INLINE unionsWith #-} -- Inline for list fusion

-- | \(O(\min(n, m \log \frac{2^W}{m})), m \leq n\).
-- The (left-biased) union of two maps.
Expand All @@ -1238,8 +1240,8 @@ union m1 m2
-- Also see the performance note on 'fromListWith'.

unionWith :: (a -> a -> a) -> IntMap a -> IntMap a -> IntMap a
unionWith f m1 m2
= unionWithKey (\_ x y -> f x y) m1 m2
unionWith f = unionWithKey (\_ x y -> f x y)
{-# INLINE unionWith #-}

-- | \(O(\min(n, m \log \frac{2^W}{m})), m \leq n\).
-- The union with a combining function.
Expand All @@ -1255,6 +1257,7 @@ unionWithKey f m1 m2
where
f' (Tip k1 x1) (Tip _k2 x2) = Tip k1 (f k1 x1 x2)
f' _ _ = error "not Tip"
{-# INLINABLE unionWithKey #-} -- See Note [INLINABLE to expose unfoldings]

{--------------------------------------------------------------------
Difference
Expand All @@ -1276,8 +1279,8 @@ difference m1 m2
-- > == singleton 3 "b:B"

differenceWith :: (a -> b -> Maybe a) -> IntMap a -> IntMap b -> IntMap a
differenceWith f m1 m2
= differenceWithKey (\_ x y -> f x y) m1 m2
differenceWith f = differenceWithKey (\_ x y -> f x y)
{-# INLINE differenceWith #-}

-- | \(O(\min(n, m \log \frac{2^W}{m})), m \leq n\).
-- Difference with a combining function. When two equal keys are
Expand All @@ -1292,7 +1295,7 @@ differenceWith f m1 m2
differenceWithKey :: (Key -> a -> b -> Maybe a) -> IntMap a -> IntMap b -> IntMap a
differenceWithKey f m1 m2
= mergeWithKey f id (const Nil) m1 m2

{-# INLINABLE differenceWithKey #-} -- See Note [INLINABLE to expose unfoldings]

-- | \(O(\min(n, m \log \frac{2^W}{m})), m \leq n\).
-- Remove all the keys in a given set from a map.
Expand Down Expand Up @@ -1417,8 +1420,8 @@ w2i = fromIntegral
-- > intersectionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "aA"

intersectionWith :: (a -> b -> c) -> IntMap a -> IntMap b -> IntMap c
intersectionWith f m1 m2
= intersectionWithKey (\_ x y -> f x y) m1 m2
intersectionWith f = intersectionWithKey (\_ x y -> f x y)
{-# INLINE intersectionWith #-}

-- | \(O(\min(n, m \log \frac{2^W}{m})), m \leq n\).
-- The intersection with a combining function.
Expand All @@ -1432,6 +1435,8 @@ intersectionWithKey f m1 m2
where
f' (Tip k1 x1) (Tip _k2 x2) = Tip k1 (f k1 x1 x2)
f' _ _ = error "not Tip"
-- See Note [INLINABLE to expose unfoldings]
{-# INLINABLE intersectionWithKey #-}

{--------------------------------------------------------------------
Symmetric difference
Expand Down Expand Up @@ -2055,7 +2060,7 @@ traverseMaybeWithKey f = go
go (Bin p l r)
| signBranch p = liftA2 (flip (bin p)) (go r) (go l)
| otherwise = liftA2 (bin p) (go l) (go r)

{-# INLINE traverseMaybeWithKey #-}

-- | Merge two maps.
--
Expand Down Expand Up @@ -2726,6 +2731,7 @@ mapAccumRWithKey f a t

mapKeys :: (Key->Key) -> IntMap a -> IntMap a
mapKeys f t = finishB (foldlWithKey' (\b kx x -> insertB (f kx) x b) emptyB t)
{-# INLINABLE mapKeys #-} -- See Note [INLINABLE to expose unfoldings]

-- | \(O(n \min(n,W))\).
-- @'mapKeysWith' c f s@ is the map obtained by applying @f@ to each key of @s@.
Expand All @@ -2745,6 +2751,7 @@ mapKeys f t = finishB (foldlWithKey' (\b kx x -> insertB (f kx) x b) emptyB t)
mapKeysWith :: (a -> a -> a) -> (Key->Key) -> IntMap a -> IntMap a
mapKeysWith c f t =
finishB (foldlWithKey' (\b kx x -> insertWithB c (f kx) x b) emptyB t)
{-# INLINABLE mapKeysWith #-} -- See Note [INLINABLE to expose unfoldings]

-- | \(O(n)\).
-- @'mapKeysMonotonic' f s == 'mapKeys' f s@, but works only when @f@
Expand All @@ -2768,6 +2775,7 @@ mapKeysWith c f t =
mapKeysMonotonic :: (Key->Key) -> IntMap a -> IntMap a
mapKeysMonotonic f t =
ascLinkAll (foldlWithKey' (\s kx x -> ascInsert s (f kx) x) MSNada t)
{-# INLINABLE mapKeysMonotonic #-} -- See Note [INLINABLE to expose unfoldings]

{--------------------------------------------------------------------
Filter
Expand All @@ -2779,8 +2787,8 @@ mapKeysMonotonic f t =
-- > filter (< "a") (fromList [(5,"a"), (3,"b")]) == empty

filter :: (a -> Bool) -> IntMap a -> IntMap a
filter p m
= filterWithKey (\_ x -> p x) m
filter p = filterWithKey (\_ x -> p x)
{-# INLINE filter #-}

-- | \(O(n)\). Keep all keys that satisfy some predicate.
--
Expand All @@ -2794,6 +2802,7 @@ filter p m

filterKeys :: (Key -> Bool) -> IntMap a -> IntMap a
filterKeys predicate = filterWithKey (\k _ -> predicate k)
{-# INLINE filterKeys #-}

-- | \(O(n)\). Keep all keys\/values that satisfy some predicate.
--
Expand All @@ -2805,6 +2814,7 @@ filterWithKey predicate = go
go Nil = Nil
go t@(Tip k x) = if predicate k x then t else Nil
go (Bin p l r) = bin p (go l) (go r)
{-# INLINABLE filterWithKey #-} -- See Note [INLINABLE to expose unfoldings]

-- | \(O(n)\). Partition the map according to some predicate. The first
-- map contains all elements that satisfy the predicate, the second all
Expand All @@ -2815,8 +2825,8 @@ filterWithKey predicate = go
-- > partition (> "x") (fromList [(5,"a"), (3,"b")]) == (empty, fromList [(3, "b"), (5, "a")])

partition :: (a -> Bool) -> IntMap a -> (IntMap a,IntMap a)
partition p m
= partitionWithKey (\_ x -> p x) m
partition p = partitionWithKey (\_ x -> p x)
{-# INLINE partition #-}

-- | \(O(n)\). Partition the map according to some predicate. The first
-- map contains all elements that satisfy the predicate, the second all
Expand Down Expand Up @@ -4438,3 +4448,31 @@ withEmpty bars = " ":bars
-- once. This allows `f` to be inlined into `go` even if `f` is big, since
-- it's likely to be the only place `f` is used, and not inlining `f` means
-- missing out on optimizations. See GHC #25259 for more on this.

-- Note [INLINABLE to expose unfoldings]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- We have many functions that could be inlined (i.e. not recursive at the top
-- level) but we mark a function with the INLINE pragma only if believe that
-- it will simplify after inlining and improve performance in most situations.
-- Otherwise, inlining just increases code size and compilation times. Fold
-- functions are good examples of functions we surely want to INLINE.
--
-- For the rest, depending on the function, e.g. if it closes over a
-- user-supplied function, it may improve performance to inline it in certain
-- situations. We want to allow the user to force inlining with GHC.Exts.inline
-- in such situations, so we mark the function as INLINABLE to make its
-- unfolding available in the interface file.
--
-- For reference see
-- https://downloads.haskell.org/ghc/9.14.1/docs/users_guide/exts/pragmas.html#inlinable-pragma.
--
-- Note that the user's ability to inline is limited to the body of the
-- function.
--
-- unionWith f = unionWithKey (\_k x y -> f x y)
-- {-# INLINABLE unionWith #-}
-- unionWithKey f = ...large rhs...
-- {-# INLINABLE unionWithKey #-}
--
-- Writing `GHC.Exts.inline unionWith` doesn't also inline the body of
-- unionWithKey. If the user wants that, they have to use unionWithKey instead.
22 changes: 16 additions & 6 deletions containers/src/Data/IntMap/Strict/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,7 @@ alterF f k m = (<$> f mv) $ \fres ->
unionsWith :: Foldable f => (a->a->a) -> f (IntMap a) -> IntMap a
unionsWith f ts
= Foldable.foldl' (unionWith f) empty ts
{-# INLINE unionsWith #-} -- Inline for list fusion

-- | \(O(\min(n, m \log \frac{2^W}{m})), m \leq n\).
-- The union with a combining function.
Expand All @@ -655,8 +656,8 @@ unionsWith f ts
-- Also see the performance note on 'fromListWith'.

unionWith :: (a -> a -> a) -> IntMap a -> IntMap a -> IntMap a
unionWith f m1 m2
= unionWithKey (\_ x y -> f x y) m1 m2
unionWith f = unionWithKey (\_ x y -> f x y)
{-# INLINE unionWith #-}

-- | \(O(\min(n, m \log \frac{2^W}{m})), m \leq n\).
-- The union with a combining function.
Expand All @@ -672,6 +673,8 @@ unionWithKey f m1 m2
where
f' (Tip k1 x1) (Tip _k2 x2) = Tip k1 $! f k1 x1 x2
f' _ _ = error "not Tip"
-- See Note [INLINABLE to expose unfoldings] in Data.IntMap.Internal
{-# INLINABLE unionWithKey #-}

{--------------------------------------------------------------------
Difference
Expand All @@ -685,8 +688,8 @@ unionWithKey f m1 m2
-- > == singleton 3 "b:B"

differenceWith :: (a -> b -> Maybe a) -> IntMap a -> IntMap b -> IntMap a
differenceWith f m1 m2
= differenceWithKey (\_ x y -> f x y) m1 m2
differenceWith f = differenceWithKey (\_ x y -> f x y)
{-# INLINE differenceWith #-}

-- | \(O(\min(n, m \log \frac{2^W}{m})), m \leq n\).
-- Difference with a combining function. When two equal keys are
Expand All @@ -701,6 +704,8 @@ differenceWith f m1 m2
differenceWithKey :: (Key -> a -> b -> Maybe a) -> IntMap a -> IntMap b -> IntMap a
differenceWithKey f m1 m2
= mergeWithKey f id (const Nil) m1 m2
-- See Note [INLINABLE to expose unfoldings] in Data.IntMap.Internal
{-# INLINABLE differenceWithKey #-}

{--------------------------------------------------------------------
Intersection
Expand All @@ -712,8 +717,8 @@ differenceWithKey f m1 m2
-- > intersectionWith (++) (fromList [(5, "a"), (3, "b")]) (fromList [(5, "A"), (7, "C")]) == singleton 5 "aA"

intersectionWith :: (a -> b -> c) -> IntMap a -> IntMap b -> IntMap c
intersectionWith f m1 m2
= intersectionWithKey (\_ x y -> f x y) m1 m2
intersectionWith f = intersectionWithKey (\_ x y -> f x y)
{-# INLINE intersectionWith #-}

-- | \(O(\min(n, m \log \frac{2^W}{m})), m \leq n\).
-- The intersection with a combining function.
Expand All @@ -727,6 +732,8 @@ intersectionWithKey f m1 m2
where
f' (Tip k1 x1) (Tip _k2 x2) = Tip k1 $! f k1 x1 x2
f' _ _ = error "not Tip"
-- See Note [INLINABLE to expose unfoldings] in Data.IntMap.Internal
{-# INLINABLE intersectionWithKey #-}

{--------------------------------------------------------------------
MergeWithKey
Expand Down Expand Up @@ -926,6 +933,7 @@ traverseMaybeWithKey f = go
go (Bin p l r)
| signBranch p = liftA2 (flip (bin p)) (go r) (go l)
| otherwise = liftA2 (bin p) (go l) (go r)
{-# INLINE traverseMaybeWithKey #-}

-- | \(O(n)\). The function @'mapAccum'@ threads an accumulating
-- argument through the map in ascending order of keys.
Expand Down Expand Up @@ -1004,6 +1012,8 @@ mapAccumRWithKey f0 a0 t0 = toPair $ go f0 a0 t0
mapKeysWith :: (a -> a -> a) -> (Key->Key) -> IntMap a -> IntMap a
mapKeysWith c f t =
finishB (foldlWithKey' (\b kx x -> insertWithB c (f kx) x b) emptyB t)
-- See Note [INLINABLE to expose unfoldings] in Data.IntMap.Internal
{-# INLINABLE mapKeysWith #-}

{--------------------------------------------------------------------
Filter
Expand Down
8 changes: 7 additions & 1 deletion containers/src/Data/IntSet/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ alterF f k s = fmap choose (f member_)
unions :: Foldable f => f IntSet -> IntSet
unions xs
= Foldable.foldl' union empty xs

{-# INLINE unions #-} -- Inline for list fusion

-- | \(O(\min(n, m \log \frac{2^W}{m})), m \leq n\).
-- The union of two sets.
Expand Down Expand Up @@ -965,6 +965,8 @@ mapMaybe f t = finishB (foldl' go emptyB t)
where go b x = case f x of
Nothing -> b
Just x' -> insertB x' b
-- See Note [INLINABLE to expose unfoldings] in Data.IntMap.Internal
{-# INLINABLE mapMaybe #-}

-- | \(O(n)\). partition the set according to some predicate.
partition :: (Key -> Bool) -> IntSet -> (IntSet,IntSet)
Expand Down Expand Up @@ -1276,6 +1278,8 @@ deleteMax = maybe Nil snd . maxView

map :: (Key -> Key) -> IntSet -> IntSet
map f t = finishB (foldl' (\b x -> insertB (f x) b) emptyB t)
-- See Note [INLINABLE to expose unfoldings] in Data.IntMap.Internal
{-# INLINABLE map #-}

-- | \(O(n)\). The
--
Expand All @@ -1293,6 +1297,8 @@ map f t = finishB (foldl' (\b x -> insertB (f x) b) emptyB t)
-- @since 0.6.3.1
mapMonotonic :: (Key -> Key) -> IntSet -> IntSet
mapMonotonic f t = ascLinkAll (foldl' (\s x -> ascInsert s (f x)) MSNada t)
-- See Note [INLINABLE to expose unfoldings] in Data.IntMap.Internal
{-# INLINABLE mapMonotonic #-}

{--------------------------------------------------------------------
Fold
Expand Down
5 changes: 4 additions & 1 deletion containers/src/Data/Map/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1742,7 +1742,7 @@ maxView t = case maxViewWithKey t of
unions :: (Foldable f, Ord k) => f (Map k a) -> Map k a
unions ts
= Foldable.foldl' union empty ts
{-# INLINABLE unions #-}
{-# INLINE unions #-} -- Inline for list fusion

-- | The union of a list of maps, with a combining operation:
-- (@'unionsWith' f == 'Prelude.foldl' ('unionWith' f) 'empty'@).
Expand Down Expand Up @@ -2972,6 +2972,7 @@ traverseMaybeWithKey = go
combine !l' mx !r' = case mx of
Nothing -> link2 l' r'
Just x' -> link kx x' l' r'
{-# INLINABLE traverseMaybeWithKey #-}

-- | \(O(n)\). Map values and separate the 'Left' and 'Right' results.
--
Expand Down Expand Up @@ -3182,6 +3183,8 @@ mapAssocsMonotonic f = go
go Tip = Tip
go (Bin sz k1 x1 l r) = case f k1 x1 of
(k2, x2) -> Bin sz k2 x2 (go l) (go r)
-- See Note [INLINABLE to expose unfoldings] in Data.IntMap.Internal
{-# INLINABLE mapAssocsMonotonic #-}

{--------------------------------------------------------------------
Folds
Expand Down
3 changes: 3 additions & 0 deletions containers/src/Data/Map/Strict/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1220,6 +1220,7 @@ traverseMaybeWithKey = go
combine !l' mx !r' = case mx of
Nothing -> link2 l' r'
Just !x' -> link kx x' l' r'
{-# INLINABLE traverseMaybeWithKey #-}

-- | \(O(n)\). Map values and separate the 'Left' and 'Right' results.
--
Expand Down Expand Up @@ -1397,6 +1398,8 @@ mapAssocsMonotonic f = go
go Tip = Tip
go (Bin sz k1 x1 l r) = case f k1 x1 of
(k2, !x2) -> Bin sz k2 x2 (go l) (go r)
-- See Note [INLINABLE to expose unfoldings] in Data.IntMap.Internal
{-# INLINABLE mapAssocsMonotonic #-}

{--------------------------------------------------------------------
Conversions
Expand Down
2 changes: 1 addition & 1 deletion containers/src/Data/Set/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -840,7 +840,7 @@ deleteMax Tip = Tip
-- | The union of the sets in a Foldable structure : (@'unions' == 'foldl' 'union' 'empty'@).
unions :: (Foldable f, Ord a) => f (Set a) -> Set a
unions = Foldable.foldl' union empty
{-# INLINABLE unions #-}
{-# INLINE unions #-} -- Inline for list fusion

-- | \(O\bigl(m \log\bigl(\frac{n}{m}+1\bigr)\bigr), \; 0 < m \leq n\). The union of two sets, preferring the first set when
-- equal elements are encountered.
Expand Down
Loading