@@ -367,6 +367,10 @@ module Data.Map.Internal (
367367 , Identity (.. )
368368 , Stack (.. )
369369 , foldl'Stack
370+ , MapBuilder (.. )
371+ , emptyB
372+ , insertB
373+ , finishB
370374
371375 -- Used by Map.Merge.Lazy
372376 , mapWhenMissing
@@ -388,7 +392,6 @@ import Data.Semigroup (Semigroup((<>)))
388392#endif
389393import Control.Applicative (Const (.. ))
390394import Control.DeepSeq (NFData (rnf ))
391- import Data.Bits (shiftL , shiftR )
392395import qualified Data.Foldable as Foldable
393396import Data.Bifoldable
394397import Utils.Containers.Internal.Prelude hiding
@@ -3256,7 +3259,7 @@ mapAccumRWithKey f a (Bin sx kx x l r) =
32563259-- > mapKeys (\ _ -> 3) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 3 "c"
32573260
32583261mapKeys :: Ord k2 => (k1 -> k2 ) -> Map k1 a -> Map k2 a
3259- mapKeys f = fromList . foldrWithKey ( \ k x xs -> (f k, x) : xs) []
3262+ mapKeys f m = finishB (foldlWithKey' ( \ b kx x -> insertB (f kx) x b) emptyB m)
32603263#if __GLASGOW_HASKELL__
32613264{-# INLINABLE mapKeys #-}
32623265#endif
@@ -3275,7 +3278,8 @@ mapKeys f = fromList . foldrWithKey (\k x xs -> (f k, x) : xs) []
32753278-- Also see the performance note on 'fromListWith'.
32763279
32773280mapKeysWith :: Ord k2 => (a -> a -> a ) -> (k1 -> k2 ) -> Map k1 a -> Map k2 a
3278- mapKeysWith c f = fromListWith c . foldrWithKey (\ k x xs -> (f k, x) : xs) []
3281+ mapKeysWith c f m =
3282+ finishB (foldlWithKey' (\ b kx x -> insertWithB c (f kx) x b) emptyB m)
32793283#if __GLASGOW_HASKELL__
32803284{-# INLINABLE mapKeysWith #-}
32813285#endif
@@ -3526,46 +3530,9 @@ instance (Ord k) => GHCExts.IsList (Map k v) where
35263530-- > fromList [(5,"a"), (3,"b"), (5, "c")] == fromList [(5,"c"), (3,"b")]
35273531-- > fromList [(5,"c"), (3,"b"), (5, "a")] == fromList [(5,"a"), (3,"b")]
35283532
3529- -- For some reason, when 'singleton' is used in fromList or in
3530- -- create, it is not inlined, so we inline it manually.
35313533fromList :: Ord k => [(k ,a )] -> Map k a
3532- fromList [] = Tip
3533- fromList [(kx, x)] = Bin 1 kx x Tip Tip
3534- fromList ((kx0, x0) : xs0) | not_ordered kx0 xs0 = fromList' (Bin 1 kx0 x0 Tip Tip ) xs0
3535- | otherwise = go (1 :: Int ) (Bin 1 kx0 x0 Tip Tip ) xs0
3536- where
3537- not_ordered _ [] = False
3538- not_ordered kx ((ky,_) : _) = kx >= ky
3539- {-# INLINE not_ordered #-}
3540-
3541- fromList' t0 xs = Foldable. foldl' ins t0 xs
3542- where ins t (k,x) = insert k x t
3543-
3544- go ! _ t [] = t
3545- go _ t [(kx, x)] = insertMax kx x t
3546- go s l xs@ ((kx, x) : xss) | not_ordered kx xss = fromList' l xs
3547- | otherwise = case create s xss of
3548- (r, ys, [] ) -> go (s `shiftL` 1 ) (link kx x l r) ys
3549- (r, _, ys) -> fromList' (link kx x l r) ys
3550-
3551- -- The create is returning a triple (tree, xs, ys). Both xs and ys
3552- -- represent not yet processed elements and only one of them can be nonempty.
3553- -- If ys is nonempty, the keys in ys are not ordered with respect to tree
3554- -- and must be inserted using fromList'. Otherwise the keys have been
3555- -- ordered so far.
3556- create ! _ [] = (Tip , [] , [] )
3557- create s xs@ (xp : xss)
3558- | s == 1 = case xp of (kx, x) | not_ordered kx xss -> (Bin 1 kx x Tip Tip , [] , xss)
3559- | otherwise -> (Bin 1 kx x Tip Tip , xss, [] )
3560- | otherwise = case create (s `shiftR` 1 ) xs of
3561- res@ (_, [] , _) -> res
3562- (l, [(ky, y)], zs) -> (insertMax ky y l, [] , zs)
3563- (l, ys@ ((ky, y): yss), _) | not_ordered ky yss -> (l, [] , ys)
3564- | otherwise -> case create (s `shiftR` 1 ) yss of
3565- (r, zs, ws) -> (link ky y l r, zs, ws)
3566- #if __GLASGOW_HASKELL__
3567- {-# INLINABLE fromList #-}
3568- #endif
3534+ fromList xs = finishB (Foldable. foldl' (\ b (kx, x) -> insertB kx x b) emptyB xs)
3535+ {-# INLINE fromList #-} -- INLINE for fusion
35693536
35703537-- | \(O(n \log n)\). Build a map from a list of key\/value pairs with a combining function. See also 'fromAscListWith'.
35713538--
@@ -3604,11 +3571,9 @@ fromList ((kx0, x0) : xs0) | not_ordered kx0 xs0 = fromList' (Bin 1 kx0 x0 Tip T
36043571-- > fromListWith (++) $ reverse $ map (\(k, v) -> (k, [v])) someListOfTuples
36053572
36063573fromListWith :: Ord k => (a -> a -> a ) -> [(k ,a )] -> Map k a
3607- fromListWith f xs
3608- = fromListWithKey (\ _ x y -> f x y) xs
3609- #if __GLASGOW_HASKELL__
3610- {-# INLINABLE fromListWith #-}
3611- #endif
3574+ fromListWith f xs =
3575+ finishB (Foldable. foldl' (\ b (kx, x) -> insertWithB f kx x b) emptyB xs)
3576+ {-# INLINE fromListWith #-} -- INLINE for fusion
36123577
36133578-- | \(O(n \log n)\). Build a map from a list of key\/value pairs with a combining function. See also 'fromAscListWithKey'.
36143579--
@@ -3619,13 +3584,9 @@ fromListWith f xs
36193584-- Also see the performance note on 'fromListWith'.
36203585
36213586fromListWithKey :: Ord k => (k -> a -> a -> a ) -> [(k ,a )] -> Map k a
3622- fromListWithKey f xs
3623- = Foldable. foldl' ins empty xs
3624- where
3625- ins t (k,x) = insertWithKey f k x t
3626- #if __GLASGOW_HASKELL__
3627- {-# INLINABLE fromListWithKey #-}
3628- #endif
3587+ fromListWithKey f xs =
3588+ finishB (Foldable. foldl' (\ b (kx, x) -> insertWithB (f kx) kx x b) emptyB xs)
3589+ {-# INLINE fromListWithKey #-} -- INLINE for fusion
36293590
36303591-- | \(O(n)\). Convert the map to a list of key\/value pairs. Subject to list fusion.
36313592--
@@ -4020,6 +3981,57 @@ splitMember k0 m = case go k0 m of
40203981
40213982data StrictTriple a b c = StrictTriple ! a ! b ! c
40223983
3984+ {- -------------------------------------------------------------------
3985+ MapBuilder
3986+ --------------------------------------------------------------------}
3987+
3988+ -- See Note [SetBuilder] in Data.Set.Internal
3989+
3990+ data MapBuilder k a
3991+ = BAsc ! (Stack k a )
3992+ | BMap ! (Map k a )
3993+
3994+ -- Empty builder.
3995+ emptyB :: MapBuilder k a
3996+ emptyB = BAsc Nada
3997+
3998+ -- Insert a key and value. Replaces the old value if one already exists for
3999+ -- the key.
4000+ insertB :: Ord k => k -> a -> MapBuilder k a -> MapBuilder k a
4001+ insertB ! ky y b = case b of
4002+ BAsc stk -> case stk of
4003+ Push kx x l stk' -> case compare ky kx of
4004+ LT -> BMap (insert ky y (ascLinkAll stk))
4005+ EQ -> BAsc (Push ky y l stk')
4006+ GT -> case l of
4007+ Tip -> BAsc (ascLinkTop stk' 1 (singleton kx x) ky y)
4008+ Bin {} -> BAsc (Push ky y Tip stk)
4009+ Nada -> BAsc (Push ky y Tip Nada )
4010+ BMap m -> BMap (insert ky y m)
4011+ {-# INLINE insertB #-}
4012+
4013+ -- Insert a key and value. The new value is combined with the old value if one
4014+ -- already exists for the key.
4015+ insertWithB
4016+ :: Ord k => (a -> a -> a ) -> k -> a -> MapBuilder k a -> MapBuilder k a
4017+ insertWithB f ! ky y b = case b of
4018+ BAsc stk -> case stk of
4019+ Push kx x l stk' -> case compare ky kx of
4020+ LT -> BMap (insertWith f ky y (ascLinkAll stk))
4021+ EQ -> BAsc (Push ky (f y x) l stk')
4022+ GT -> case l of
4023+ Tip -> BAsc (ascLinkTop stk' 1 (singleton kx x) ky y)
4024+ Bin {} -> BAsc (Push ky y Tip stk)
4025+ Nada -> BAsc (Push ky y Tip Nada )
4026+ BMap m -> BMap (insertWith f ky y m)
4027+ {-# INLINE insertWithB #-}
4028+
4029+ -- Finalize the builder into a Map.
4030+ finishB :: MapBuilder k a -> Map k a
4031+ finishB (BAsc stk) = ascLinkAll stk
4032+ finishB (BMap m) = m
4033+ {-# INLINABLE finishB #-}
4034+
40234035{- -------------------------------------------------------------------
40244036 Utility functions that maintain the balance properties of the tree.
40254037 All constructors assume that all values in [l] < [k] and all values
0 commit comments