3
3
{-# LANGUAGE PatternGuards #-}
4
4
#if defined(__GLASGOW_HASKELL__)
5
5
{-# LANGUAGE DeriveLift #-}
6
+ {-# LANGUAGE UnboxedTuples #-}
6
7
{-# LANGUAGE RoleAnnotations #-}
7
8
{-# LANGUAGE StandaloneDeriving #-}
8
9
{-# LANGUAGE Trustworthy #-}
@@ -236,7 +237,9 @@ module Data.Map.Internal (
236
237
-- * Traversal
237
238
-- ** Map
238
239
, map
240
+ , mapU
239
241
, mapWithKey
242
+ , mapWithKeyU
240
243
, traverseWithKey
241
244
, traverseMaybeWithKey
242
245
, mapAccum
@@ -301,6 +304,7 @@ module Data.Map.Internal (
301
304
302
305
, mapMaybe
303
306
, mapMaybeWithKey
307
+ , mapMaybeWithKeyU
304
308
, mapEither
305
309
, mapEitherWithKey
306
310
@@ -407,6 +411,8 @@ import Data.Data
407
411
import qualified Control.Category as Category
408
412
import Data.Coerce
409
413
#endif
414
+ import Utils.Containers.Internal.UnboxedMaybe
415
+ import Utils.Containers.Internal.UnboxedSolo
410
416
411
417
412
418
{- -------------------------------------------------------------------
@@ -2849,6 +2855,7 @@ isProperSubmapOfBy f t1 t2
2849
2855
filter :: (a -> Bool ) -> Map k a -> Map k a
2850
2856
filter p m
2851
2857
= filterWithKey (\ _ x -> p x) m
2858
+ {-# INLINE filter #-}
2852
2859
2853
2860
-- | \(O(n)\). Filter all keys\/values that satisfy the predicate.
2854
2861
--
@@ -2863,6 +2870,32 @@ filterWithKey p t@(Bin _ kx x l r)
2863
2870
| otherwise = link2 pl pr
2864
2871
where ! pl = filterWithKey p l
2865
2872
! 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
+ #-}
2866
2899
2867
2900
-- | \(O(n)\). Filter keys and values using an 'Applicative'
2868
2901
-- predicate.
@@ -2977,17 +3010,60 @@ partitionWithKey p0 t0 = toPair $ go p0 t0
2977
3010
2978
3011
mapMaybe :: (a -> Maybe b ) -> Map k a -> Map k b
2979
3012
mapMaybe f = mapMaybeWithKey (\ _ x -> f x)
3013
+ {-# INLINE mapMaybe #-}
2980
3014
2981
3015
-- | \(O(n)\). Map keys\/values and collect the 'Just' results.
2982
3016
--
2983
3017
-- > let f k _ = if k < 5 then Just ("key : " ++ (show k)) else Nothing
2984
3018
-- > mapMaybeWithKey f (fromList [(5,"a"), (3,"b")]) == singleton 3 "key : 3"
2985
3019
2986
3020
mapMaybeWithKey :: (k -> a -> Maybe b ) -> Map k a -> Map k b
3021
+ {-
2987
3022
mapMaybeWithKey _ Tip = Tip
2988
3023
mapMaybeWithKey f (Bin _ kx x l r) = case f kx x of
2989
3024
Just y -> link kx y (mapMaybeWithKey f l) (mapMaybeWithKey f r)
2990
3025
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
+ #-}
2991
3067
2992
3068
-- | \(O(n)\). Traverse keys\/values and collect the 'Just' results.
2993
3069
--
@@ -3045,17 +3121,41 @@ mapEitherWithKey f0 t0 = toPair $ go f0 t0
3045
3121
-- > map (++ "x") (fromList [(5,"a"), (3,"b")]) == fromList [(3, "bx"), (5, "ax")]
3046
3122
3047
3123
map :: (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
3048
3133
map f = go where
3049
3134
go Tip = Tip
3050
3135
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
3054
3137
3055
3138
#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 #-}
3057
3157
{-# 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
3059
3159
"map/coerce" map coerce = coerce
3060
3160
#-}
3061
3161
#endif
@@ -3066,21 +3166,38 @@ map f = go where
3066
3166
-- > mapWithKey f (fromList [(5,"a"), (3,"b")]) == fromList [(3, "3:b"), (5, "5:a")]
3067
3167
3068
3168
mapWithKey :: (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
3069
3173
mapWithKey _ Tip = Tip
3070
3174
mapWithKey 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
3071
3190
3072
3191
#ifdef __GLASGOW_HASKELL__
3073
- {-# NOINLINE [1] mapWithKey #-}
3192
+ {-# NOINLINE [1] mapWithKeyU #-}
3074
3193
{-# 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
3081
3197
#-}
3082
3198
#endif
3083
3199
3200
+
3084
3201
-- | \(O(n)\).
3085
3202
-- @'traverseWithKey' f m == 'fromList' <$> 'traverse' (\(k, v) -> (,) k <$> f k v) ('toList' m)@
3086
3203
-- 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
4195
4312
--------------------------------------------------------------------}
4196
4313
instance Functor (Map k ) where
4197
4314
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 (<$) #-}
4202
4321
4203
4322
-- | Traverses in order of increasing key.
4204
4323
instance Traversable (Map k ) where
0 commit comments