@@ -237,8 +237,10 @@ module Data.IntMap.Internal (
237237 , fromAscList
238238 , fromAscListWith
239239 , fromAscListWithKey
240+ , fromAscListUpsert
240241 , fromDistinctAscList
241242 , fromDescList
243+ , fromDescListUpsert
242244
243245 -- * Filter
244246 , filter
@@ -3588,6 +3590,8 @@ fromAscList xs =
35883590-- > fromAscListWith (++) [(3,"b"), (5,"a"), (5,"b")] == fromList [(3, "b"), (5, "ba")]
35893591--
35903592-- Also see the performance note on 'fromListWith'.
3593+ --
3594+ -- See also: 'fromAscListUpsert'
35913595
35923596fromAscListWith :: (a -> a -> a ) -> [(Key ,a )] -> IntMap a
35933597fromAscListWith f xs = fromAscListWithKey (\ _ x y -> f x y) xs
@@ -3605,6 +3609,8 @@ fromAscListWith f xs = fromAscListWithKey (\_ x y -> f x y) xs
36053609-- > fromAscListWithKey f [] == empty
36063610--
36073611-- Also see the performance note on 'fromListWith'.
3612+ --
3613+ -- See also: 'fromAscListUpsert'
36083614
36093615-- See Note [fromAscList implementation]
36103616fromAscListWithKey :: (Key -> a -> a -> a ) -> [(Key ,a )] -> IntMap a
@@ -3618,6 +3624,29 @@ fromAscListWithKey f xs = ascLinkAll (Foldable.foldl' next MSNada xs)
36183624 in MSPush ky y (ascLinkTop stk kx (Tip kx x) m)
36193625{-# INLINE fromAscListWithKey #-} -- Inline for list fusion
36203626
3627+ -- | \(O(n)\). Build a map from an ascending list in linear time with a
3628+ -- combining function for equal keys.
3629+ --
3630+ -- __Warning__: This function should be used only if the keys are in
3631+ -- non-decreasing order. This precondition is not checked. Use 'fromListUpsert'
3632+ -- if the precondition may not hold.
3633+ --
3634+ -- > let f x = maybe [x] (x:)
3635+ -- > fromAscListUpsert f [(3,'a'), (3,'b'), (5,'c'), (5,'d'), (5,'e')] == fromList [(3,"ba"), (5,"edc")]
3636+ --
3637+ -- @since FIXME
3638+ fromAscListUpsert :: (a -> Maybe b -> b ) -> [(Key , a )] -> IntMap b
3639+ fromAscListUpsert f xs = ascLinkAll (Foldable. foldl' next MSNada xs)
3640+ where
3641+ next s (! ky, y) = case s of
3642+ MSNada -> MSPush ky (f y Nothing ) Nada
3643+ MSPush kx x stk
3644+ | kx == ky -> MSPush ky (f y (Just x)) stk
3645+ | otherwise ->
3646+ let m = branchMask kx ky
3647+ in MSPush ky (f y Nothing ) (ascLinkTop stk kx (Tip kx x) m)
3648+ {-# INLINE fromAscListUpsert #-} -- Inline for list fusion
3649+
36213650-- | \(O(n)\). Build a map from a list of key\/value pairs where
36223651-- the keys are in ascending order and all distinct.
36233652--
@@ -3652,6 +3681,29 @@ fromDescList xs =
36523681 descLinkAll (Foldable. foldl' (\ s (ky, y) -> descInsert ky y s) MSNada xs)
36533682{-# INLINE fromDescList #-} -- Inline for list fusion
36543683
3684+ -- | \(O(n)\). Build a map from a descending list in linear time with a
3685+ -- combining function for equal keys.
3686+ --
3687+ -- __Warning__: This function should be used only if the keys are in
3688+ -- non-increasing order. This precondition is not checked. Use 'fromListUpsert'
3689+ -- if the precondition may not hold.
3690+ --
3691+ -- > let f x = maybe [x] (x:)
3692+ -- > fromDescListUpsert f [(5,'a'), (5,'b'), (5,'c'), (3,'d'), (3,'e')] == fromList [(3,"ed"), (5,"cba")]
3693+ --
3694+ -- @since FIXME
3695+ fromDescListUpsert :: (a -> Maybe b -> b ) -> [(Key , a )] -> IntMap b
3696+ fromDescListUpsert f xs = descLinkAll (Foldable. foldl' next MSNada xs)
3697+ where
3698+ next s (! ky, y) = case s of
3699+ MSNada -> MSPush ky (f y Nothing ) Nada
3700+ MSPush kx x stk
3701+ | kx == ky -> MSPush ky (f y (Just x)) stk
3702+ | otherwise ->
3703+ let m = branchMask kx ky
3704+ in MSPush ky (f y Nothing ) (descLinkTop kx (Tip kx x) m stk)
3705+ {-# INLINE fromDescListUpsert #-} -- Inline for list fusion
3706+
36553707data Stack a
36563708 = Nada
36573709 | Push {- # UNPACK #-} !Int ! (IntMap a ) ! (Stack a )
0 commit comments