33{-# LANGUAGE PatternGuards #-}
44#if defined(__GLASGOW_HASKELL__)
55{-# LANGUAGE DeriveLift #-}
6+ {-# LANGUAGE UnboxedTuples #-}
67{-# LANGUAGE RoleAnnotations #-}
78{-# LANGUAGE StandaloneDeriving #-}
89{-# LANGUAGE Trustworthy #-}
@@ -236,7 +237,9 @@ module Data.Map.Internal (
236237 -- * Traversal
237238 -- ** Map
238239 , map
240+ , mapU
239241 , mapWithKey
242+ , mapWithKeyU
240243 , traverseWithKey
241244 , traverseMaybeWithKey
242245 , mapAccum
@@ -301,6 +304,7 @@ module Data.Map.Internal (
301304
302305 , mapMaybe
303306 , mapMaybeWithKey
307+ , mapMaybeWithKeyU
304308 , mapEither
305309 , mapEitherWithKey
306310
@@ -407,6 +411,8 @@ import Data.Data
407411import qualified Control.Category as Category
408412import Data.Coerce
409413#endif
414+ import Utils.Containers.Internal.UnboxedMaybe
415+ import Utils.Containers.Internal.UnboxedSolo
410416
411417
412418{- -------------------------------------------------------------------
@@ -2849,6 +2855,7 @@ isProperSubmapOfBy f t1 t2
28492855filter :: (a -> Bool ) -> Map k a -> Map k a
28502856filter p m
28512857 = filterWithKey (\ _ x -> p x) m
2858+ {-# INLINE filter #-}
28522859
28532860-- | \(O(n)\). Filter all keys\/values that satisfy the predicate.
28542861--
@@ -2863,6 +2870,32 @@ filterWithKey p t@(Bin _ kx x l r)
28632870 | otherwise = link2 pl pr
28642871 where ! pl = filterWithKey p l
28652872 ! pr = filterWithKey p r
2873+ {-# NOINLINE [1] filterWithKey #-}
2874+
2875+ {-# RULES
2876+ "filterWK/filterWK" forall p q m. filterWithKey p (filterWithKey q m) =
2877+ filterWithKey (\k x -> q k x && p k x) m
2878+ "filterWK/mapU" forall p f m. filterWithKey p (mapU f m) =
2879+ mapMaybeWithKeyU (\k x -> case f x of
2880+ SoloU y
2881+ | p k y -> JustU y
2882+ | otherwise -> NothingU) m
2883+ "filterWK/mapWK#" forall p f m. filterWithKey p (mapWithKeyU f m) =
2884+ mapMaybeWithKeyU (\k x -> case f k x of
2885+ SoloU y
2886+ | p k y -> JustU y
2887+ | otherwise -> NothingU) m
2888+ "mapU/filterWK" forall f p m. mapU f (filterWithKey p m) =
2889+ mapMaybeWithKeyU (\k x ->
2890+ if p k x
2891+ then case f x of SoloU y -> JustU y
2892+ else NothingU) m
2893+ "mapWK#/filterWK" forall f p m. mapWithKeyU f (filterWithKey p m) =
2894+ mapMaybeWithKeyU (\k x ->
2895+ if p k x
2896+ then case f k x of SoloU y -> JustU y
2897+ else NothingU) m
2898+ #-}
28662899
28672900-- | \(O(n)\). Filter keys and values using an 'Applicative'
28682901-- predicate.
@@ -2977,17 +3010,54 @@ partitionWithKey p0 t0 = toPair $ go p0 t0
29773010
29783011mapMaybe :: (a -> Maybe b ) -> Map k a -> Map k b
29793012mapMaybe f = mapMaybeWithKey (\ _ x -> f x)
3013+ {-# INLINE mapMaybe #-}
29803014
29813015-- | \(O(n)\). Map keys\/values and collect the 'Just' results.
29823016--
29833017-- > let f k _ = if k < 5 then Just ("key : " ++ (show k)) else Nothing
29843018-- > mapMaybeWithKey f (fromList [(5,"a"), (3,"b")]) == singleton 3 "key : 3"
29853019
29863020mapMaybeWithKey :: (k -> a -> Maybe b ) -> Map k a -> Map k b
2987- mapMaybeWithKey _ Tip = Tip
2988- mapMaybeWithKey f (Bin _ kx x l r) = case f kx x of
2989- Just y -> link kx y (mapMaybeWithKey f l) (mapMaybeWithKey f r)
2990- Nothing -> link2 (mapMaybeWithKey f l) (mapMaybeWithKey f r)
3021+ mapMaybeWithKey f = \ m ->
3022+ mapMaybeWithKeyU (\ k x -> toMaybeU (f k x)) m
3023+ {-# INLINE mapMaybeWithKey #-}
3024+
3025+ mapMaybeWithKeyU :: (k -> a -> MaybeU b ) -> Map k a -> Map k b
3026+ mapMaybeWithKeyU _ Tip = Tip
3027+ mapMaybeWithKeyU f (Bin _ kx x l r) = case f kx x of
3028+ JustU y -> link kx y (mapMaybeWithKeyU f l) (mapMaybeWithKeyU f r)
3029+ NothingU -> link2 (mapMaybeWithKeyU f l) (mapMaybeWithKeyU f r)
3030+ {-# NOINLINE [1] mapMaybeWithKeyU #-}
3031+
3032+ {-# RULES
3033+ "mapMaybeWK#/mapU" forall f g m. mapMaybeWithKeyU f (mapU g m) =
3034+ mapMaybeWithKeyU (\k x -> case g x of SoloU y -> f k y) m
3035+ "mapU/mapMaybeWK#" forall f g m. mapU f (mapMaybeWithKeyU g m) =
3036+ mapMaybeWithKeyU
3037+ (\k x -> case g k x of
3038+ NothingU -> NothingU
3039+ JustU y -> case f y of SoloU z -> JustU z) m
3040+ "mapMaybeWK#/mapWK#" forall f g m. mapMaybeWithKeyU f (mapWithKeyU g m) =
3041+ mapMaybeWithKeyU (\k x -> case g k x of SoloU y -> f k y) m
3042+ "mapWK#/mapMaybeWK#" forall f g m. mapWithKeyU f (mapMaybeWithKeyU g m) =
3043+ mapMaybeWithKeyU
3044+ (\k x -> case g k x of
3045+ NothingU -> NothingU
3046+ JustU y -> case f k y of SoloU z -> JustU z) m
3047+ "mapMaybeWK#/mapMaybeWK#" forall f g m. mapMaybeWithKeyU f (mapMaybeWithKeyU g m) =
3048+ mapMaybeWithKeyU
3049+ (\k x -> case g k x of
3050+ NothingU -> NothingU
3051+ JustU y -> f k y) m
3052+ "mapMaybeWK#/filterWK" forall f p m. mapMaybeWithKeyU f (filterWithKey p m) =
3053+ mapMaybeWithKeyU (\k x -> if p k x then f k x else NothingU) m
3054+ "filterWK/mapMaybeWK#" forall p f m. filterWithKey p (mapMaybeWithKeyU f m) =
3055+ mapMaybeWithKeyU (\k x -> case f k x of
3056+ NothingU -> NothingU
3057+ JustU y
3058+ | p k y -> JustU y
3059+ | otherwise -> NothingU) m
3060+ #-}
29913061
29923062-- | \(O(n)\). Traverse keys\/values and collect the 'Just' results.
29933063--
@@ -3045,17 +3115,41 @@ mapEitherWithKey f0 t0 = toPair $ go f0 t0
30453115-- > map (++ "x") (fromList [(5,"a"), (3,"b")]) == fromList [(3, "bx"), (5, "ax")]
30463116
30473117map :: (a -> b ) -> Map k a -> Map k b
3118+ #ifdef __GLASGOW_HASKELL__
3119+ -- We define map using mapU solely to reduce the number of rewrite
3120+ -- rules we need.
3121+ map f = mapU (\ x -> SoloU (f x))
3122+ -- We delay inlinability of map to support map/coerce. While a
3123+ -- mapU/coerce rule seems to work when everything is done just so,
3124+ -- it feels too brittle to me for now (GHC 9.4).
3125+ {-# INLINABLE [1] map #-}
3126+ #else
30483127map f = go where
30493128 go Tip = Tip
30503129 go (Bin sx kx x l r) = Bin sx kx (f x) (go l) (go r)
3051- -- We use a `go` function to allow `map` to inline. This makes
3052- -- a big difference if someone uses `map (const x) m` instead
3053- -- of `x <$ m`; it doesn't seem to do any harm.
3130+ #endif
30543131
30553132#ifdef __GLASGOW_HASKELL__
3056- {-# NOINLINE [1] map #-}
3133+ mapU :: (a -> SoloU b ) -> Map k a -> Map k b
3134+ mapU f = go where
3135+ go Tip = Tip
3136+ go (Bin sx kx x l r)
3137+ | SoloU y <- f x
3138+ = Bin sx kx y (go l) (go r)
3139+ #if defined (__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 806) && (__GLASGOW_HASKELL__ < 810)
3140+ -- Something goes wrong checking SoloU completeness
3141+ -- in these versions
3142+ go _ = error " impossible"
3143+ #endif
3144+ -- We use a `go` function to allow `mapU` to inline. Without this,
3145+ -- we'd slow down both strict and lazy map, which wouldn't be great.
3146+ -- This also lets us avoid a custom implementation of <$
3147+
3148+ -- We don't let mapU inline until phase 0 because we need a step
3149+ -- after map inlines.
3150+ {-# NOINLINE [0] mapU #-}
30573151{-# RULES
3058- "map/map " forall f g xs . map f (map g xs) = map (f . g ) xs
3152+ "mapU/mapU " forall f g xs . mapU f (mapU g xs) = mapU (\x -> case g x of SoloU y -> f y ) xs
30593153"map/coerce" map coerce = coerce
30603154 #-}
30613155#endif
@@ -3066,21 +3160,38 @@ map f = go where
30663160-- > mapWithKey f (fromList [(5,"a"), (3,"b")]) == fromList [(3, "3:b"), (5, "5:a")]
30673161
30683162mapWithKey :: (k -> a -> b ) -> Map k a -> Map k b
3163+ #ifdef __GLASGOW_HASKELL__
3164+ mapWithKey f = mapWithKeyU (\ k a -> SoloU (f k a))
3165+ {-# INLINABLE mapWithKey #-}
3166+ #else
30693167mapWithKey _ Tip = Tip
30703168mapWithKey f (Bin sx kx x l r) = Bin sx kx (f kx x) (mapWithKey f l) (mapWithKey f r)
3169+ #endif
3170+
3171+ -- | A version of 'mapWithKey' that takes a function producing a unary
3172+ -- unboxed tuple.
3173+ mapWithKeyU :: (k -> a -> SoloU b ) -> Map k a -> Map k b
3174+ mapWithKeyU f = go where
3175+ go Tip = Tip
3176+ go (Bin sx kx x l r)
3177+ | SoloU y <- f kx x
3178+ = Bin sx kx y (go l) (go r)
3179+ #if defined (__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 806) && (__GLASGOW_HASKELL__ < 810)
3180+ -- Something goes wrong checking SoloU completeness
3181+ -- in these versions
3182+ go _ = error " impossible"
3183+ #endif
30713184
30723185#ifdef __GLASGOW_HASKELL__
3073- {-# NOINLINE [1] mapWithKey #-}
3186+ {-# NOINLINE [1] mapWithKeyU #-}
30743187{-# RULES
3075- "mapWithKey/mapWithKey" forall f g xs . mapWithKey f (mapWithKey g xs) =
3076- mapWithKey (\k a -> f k (g k a)) xs
3077- "mapWithKey/map" forall f g xs . mapWithKey f (map g xs) =
3078- mapWithKey (\k a -> f k (g a)) xs
3079- "map/mapWithKey" forall f g xs . map f (mapWithKey g xs) =
3080- mapWithKey (\k a -> f (g k a)) xs
3188+ "mapWK#/mapWK#" forall f g xs. mapWithKeyU f (mapWithKeyU g xs) = mapWithKeyU (\k x -> case g k x of SoloU y -> f k y) xs
3189+ "mapWK#/mapU" forall f g xs. mapWithKeyU f (mapU g xs) = mapWithKeyU (\k x -> case g x of SoloU y -> f k y) xs
3190+ "mapU/mapWK#" forall f g xs. mapU f (mapWithKeyU g xs) = mapWithKeyU (\k x -> case g k x of SoloU y -> f y) xs
30813191 #-}
30823192#endif
30833193
3194+
30843195-- | \(O(n)\).
30853196-- @'traverseWithKey' f m == 'fromList' <$> 'traverse' (\(k, v) -> (,) k <$> f k v) ('toList' m)@
30863197-- That is, behaves exactly like a regular 'traverse' except that the traversing
@@ -4195,10 +4306,12 @@ instance (Ord k, Read k) => Read1 (Map k) where
41954306--------------------------------------------------------------------}
41964307instance Functor (Map k ) where
41974308 fmap f m = map f m
4198- #ifdef __GLASGOW_HASKELL__
4199- _ <$ Tip = Tip
4200- a <$ (Bin sx kx _ l r) = Bin sx kx a (a <$ l) (a <$ r)
4201- #endif
4309+ {-# INLINABLE fmap #-}
4310+ a <$ m = map (const a) m
4311+ -- For some reason, we need an explicit INLINE or INLINABLE pragma to
4312+ -- get the unfolding to use map rather than expanding into a recursive
4313+ -- function that RULES will never match. Hmm....
4314+ {-# INLINABLE (<$) #-}
42024315
42034316-- | Traverses in order of increasing key.
42044317instance Traversable (Map k ) where
0 commit comments