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,60 @@ 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
3021+ {-
29873022mapMaybeWithKey _ Tip = Tip
29883023mapMaybeWithKey f (Bin _ kx x l r) = case f kx x of
29893024 Just y -> link kx y (mapMaybeWithKey f l) (mapMaybeWithKey f r)
29903025 Nothing -> link2 (mapMaybeWithKey f l) (mapMaybeWithKey f r)
3026+ -}
3027+ mapMaybeWithKey f = \ m ->
3028+ mapMaybeWithKeyU (\ k x -> toMaybeU (f k x)) m
3029+ {-# INLINE mapMaybeWithKey #-}
3030+
3031+ mapMaybeWithKeyU :: (k -> a -> MaybeU b ) -> Map k a -> Map k b
3032+ mapMaybeWithKeyU _ Tip = Tip
3033+ mapMaybeWithKeyU f (Bin _ kx x l r) = case f kx x of
3034+ JustU y -> link kx y (mapMaybeWithKeyU f l) (mapMaybeWithKeyU f r)
3035+ NothingU -> link2 (mapMaybeWithKeyU f l) (mapMaybeWithKeyU f r)
3036+ {-# NOINLINE [1] mapMaybeWithKeyU #-}
3037+
3038+ {-# RULES
3039+ "mapMaybeWK#/mapU" forall f g m. mapMaybeWithKeyU f (mapU g m) =
3040+ mapMaybeWithKeyU (\k x -> case g x of SoloU y -> f k y) m
3041+ "mapU/mapMaybeWK#" forall f g m. mapU f (mapMaybeWithKeyU g m) =
3042+ mapMaybeWithKeyU
3043+ (\k x -> case g k x of
3044+ NothingU -> NothingU
3045+ JustU y -> case f y of SoloU z -> JustU z) m
3046+ "mapMaybeWK#/mapWK#" forall f g m. mapMaybeWithKeyU f (mapWithKeyU g m) =
3047+ mapMaybeWithKeyU (\k x -> case g k x of SoloU y -> f k y) m
3048+ "mapWK#/mapMaybeWK#" forall f g m. mapWithKeyU f (mapMaybeWithKeyU g m) =
3049+ mapMaybeWithKeyU
3050+ (\k x -> case g k x of
3051+ NothingU -> NothingU
3052+ JustU y -> case f k y of SoloU z -> JustU z) m
3053+ "mapMaybeWK#/mapMaybeWK#" forall f g m. mapMaybeWithKeyU f (mapMaybeWithKeyU g m) =
3054+ mapMaybeWithKeyU
3055+ (\k x -> case g k x of
3056+ NothingU -> NothingU
3057+ JustU y -> f k y) m
3058+ "mapMaybeWK#/filterWK" forall f p m. mapMaybeWithKeyU f (filterWithKey p m) =
3059+ mapMaybeWithKeyU (\k x -> if p k x then f k x else NothingU) m
3060+ "filterWK/mapMaybeWK#" forall p f m. filterWithKey p (mapMaybeWithKeyU f m) =
3061+ mapMaybeWithKeyU (\k x -> case f k x of
3062+ NothingU -> NothingU
3063+ JustU y
3064+ | p k y -> JustU y
3065+ | otherwise -> NothingU) m
3066+ #-}
29913067
29923068-- | \(O(n)\). Traverse keys\/values and collect the 'Just' results.
29933069--
@@ -3045,17 +3121,41 @@ mapEitherWithKey f0 t0 = toPair $ go f0 t0
30453121-- > map (++ "x") (fromList [(5,"a"), (3,"b")]) == fromList [(3, "bx"), (5, "ax")]
30463122
30473123map :: (a -> b ) -> Map k a -> Map k b
3124+ #ifdef __GLASGOW_HASKELL__
3125+ -- We define map using mapU solely to reduce the number of rewrite
3126+ -- rules we need.
3127+ map f = mapU (\ x -> SoloU (f x))
3128+ -- We delay inlinability of map to support map/coerce. While a
3129+ -- mapU/coerce rule seems to work when everything is done just so,
3130+ -- it feels too brittle to me for now (GHC 9.4).
3131+ {-# INLINABLE [1] map #-}
3132+ #else
30483133map f = go where
30493134 go Tip = Tip
30503135 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.
3136+ #endif
30543137
30553138#ifdef __GLASGOW_HASKELL__
3056- {-# NOINLINE [1] map #-}
3139+ mapU :: (a -> SoloU b ) -> Map k a -> Map k b
3140+ mapU f = go where
3141+ go Tip = Tip
3142+ go (Bin sx kx x l r)
3143+ | SoloU y <- f x
3144+ = Bin sx kx y (go l) (go r)
3145+ #if defined (__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 806) && (__GLASGOW_HASKELL__ < 810)
3146+ -- Something goes wrong checking SoloU completeness
3147+ -- in these versions
3148+ go _ = error " impossible"
3149+ #endif
3150+ -- We use a `go` function to allow `mapU` to inline. Without this,
3151+ -- we'd slow down both strict and lazy map, which wouldn't be great.
3152+ -- This also lets us avoid a custom implementation of <$
3153+
3154+ -- We don't let mapU inline until phase 0 because we need a step
3155+ -- after map inlines.
3156+ {-# NOINLINE [0] mapU #-}
30573157{-# RULES
3058- "map/map " forall f g xs . map f (map g xs) = map (f . g ) xs
3158+ "mapU/mapU " forall f g xs . mapU f (mapU g xs) = mapU (\x -> case g x of SoloU y -> f y ) xs
30593159"map/coerce" map coerce = coerce
30603160 #-}
30613161#endif
@@ -3066,21 +3166,38 @@ map f = go where
30663166-- > mapWithKey f (fromList [(5,"a"), (3,"b")]) == fromList [(3, "3:b"), (5, "5:a")]
30673167
30683168mapWithKey :: (k -> a -> b ) -> Map k a -> Map k b
3169+ #ifdef __GLASGOW_HASKELL__
3170+ mapWithKey f = mapWithKeyU (\ k a -> SoloU (f k a))
3171+ {-# INLINABLE mapWithKey #-}
3172+ #else
30693173mapWithKey _ Tip = Tip
30703174mapWithKey f (Bin sx kx x l r) = Bin sx kx (f kx x) (mapWithKey f l) (mapWithKey f r)
3175+ #endif
3176+
3177+ -- | A version of 'mapWithKey' that takes a function producing a unary
3178+ -- unboxed tuple.
3179+ mapWithKeyU :: (k -> a -> SoloU b ) -> Map k a -> Map k b
3180+ mapWithKeyU f = go where
3181+ go Tip = Tip
3182+ go (Bin sx kx x l r)
3183+ | SoloU y <- f kx x
3184+ = Bin sx kx y (go l) (go r)
3185+ #if defined (__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 806) && (__GLASGOW_HASKELL__ < 810)
3186+ -- Something goes wrong checking SoloU completeness
3187+ -- in these versions
3188+ go _ = error " impossible"
3189+ #endif
30713190
30723191#ifdef __GLASGOW_HASKELL__
3073- {-# NOINLINE [1] mapWithKey #-}
3192+ {-# NOINLINE [1] mapWithKeyU #-}
30743193{-# 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
3194+ "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
3195+ "mapWK#/mapU" forall f g xs. mapWithKeyU f (mapU g xs) = mapWithKeyU (\k x -> case g x of SoloU y -> f k y) xs
3196+ "mapU/mapWK#" forall f g xs. mapU f (mapWithKeyU g xs) = mapWithKeyU (\k x -> case g k x of SoloU y -> f y) xs
30813197 #-}
30823198#endif
30833199
3200+
30843201-- | \(O(n)\).
30853202-- @'traverseWithKey' f m == 'fromList' <$> 'traverse' (\(k, v) -> (,) k <$> f k v) ('toList' m)@
30863203-- That is, behaves exactly like a regular 'traverse' except that the traversing
@@ -4195,10 +4312,12 @@ instance (Ord k, Read k) => Read1 (Map k) where
41954312--------------------------------------------------------------------}
41964313instance Functor (Map k ) where
41974314 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
4315+ {-# INLINABLE fmap #-}
4316+ a <$ m = map (const a) m
4317+ -- For some reason, we need an explicit INLINE or INLINABLE pragma to
4318+ -- get the unfolding to use map rather than expanding into a recursive
4319+ -- function that RULES will never match. Hmm....
4320+ {-# INLINABLE (<$) #-}
42024321
42034322-- | Traverses in order of increasing key.
42044323instance Traversable (Map k ) where
0 commit comments