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