@@ -367,6 +367,10 @@ module Data.Map.Internal (
367
367
, Identity (.. )
368
368
, Stack (.. )
369
369
, foldl'Stack
370
+ , MapBuilder (.. )
371
+ , emptyB
372
+ , insertB
373
+ , finishB
370
374
371
375
-- Used by Map.Merge.Lazy
372
376
, mapWhenMissing
@@ -388,7 +392,6 @@ import Data.Semigroup (Semigroup((<>)))
388
392
#endif
389
393
import Control.Applicative (Const (.. ))
390
394
import Control.DeepSeq (NFData (rnf ))
391
- import Data.Bits (shiftL , shiftR )
392
395
import qualified Data.Foldable as Foldable
393
396
import Data.Bifoldable
394
397
import Utils.Containers.Internal.Prelude hiding
@@ -3256,7 +3259,7 @@ mapAccumRWithKey f a (Bin sx kx x l r) =
3256
3259
-- > mapKeys (\ _ -> 3) (fromList [(1,"b"), (2,"a"), (3,"d"), (4,"c")]) == singleton 3 "c"
3257
3260
3258
3261
mapKeys :: 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)
3260
3263
#if __GLASGOW_HASKELL__
3261
3264
{-# INLINABLE mapKeys #-}
3262
3265
#endif
@@ -3275,7 +3278,8 @@ mapKeys f = fromList . foldrWithKey (\k x xs -> (f k, x) : xs) []
3275
3278
-- Also see the performance note on 'fromListWith'.
3276
3279
3277
3280
mapKeysWith :: 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)
3279
3283
#if __GLASGOW_HASKELL__
3280
3284
{-# INLINABLE mapKeysWith #-}
3281
3285
#endif
@@ -3526,46 +3530,9 @@ instance (Ord k) => GHCExts.IsList (Map k v) where
3526
3530
-- > fromList [(5,"a"), (3,"b"), (5, "c")] == fromList [(5,"c"), (3,"b")]
3527
3531
-- > fromList [(5,"c"), (3,"b"), (5, "a")] == fromList [(5,"a"), (3,"b")]
3528
3532
3529
- -- For some reason, when 'singleton' is used in fromList or in
3530
- -- create, it is not inlined, so we inline it manually.
3531
3533
fromList :: 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
3569
3536
3570
3537
-- | \(O(n \log n)\). Build a map from a list of key\/value pairs with a combining function. See also 'fromAscListWith'.
3571
3538
--
@@ -3604,11 +3571,9 @@ fromList ((kx0, x0) : xs0) | not_ordered kx0 xs0 = fromList' (Bin 1 kx0 x0 Tip T
3604
3571
-- > fromListWith (++) $ reverse $ map (\(k, v) -> (k, [v])) someListOfTuples
3605
3572
3606
3573
fromListWith :: 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
3612
3577
3613
3578
-- | \(O(n \log n)\). Build a map from a list of key\/value pairs with a combining function. See also 'fromAscListWithKey'.
3614
3579
--
@@ -3619,13 +3584,9 @@ fromListWith f xs
3619
3584
-- Also see the performance note on 'fromListWith'.
3620
3585
3621
3586
fromListWithKey :: 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
3629
3590
3630
3591
-- | \(O(n)\). Convert the map to a list of key\/value pairs. Subject to list fusion.
3631
3592
--
@@ -4020,6 +3981,57 @@ splitMember k0 m = case go k0 m of
4020
3981
4021
3982
data StrictTriple a b c = StrictTriple ! a ! b ! c
4022
3983
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
+
4023
4035
{- -------------------------------------------------------------------
4024
4036
Utility functions that maintain the balance properties of the tree.
4025
4037
All constructors assume that all values in [l] < [k] and all values
0 commit comments