@@ -34,18 +34,26 @@ module Data.IntMap.Strict.Refined
3434 , SingletonProof(..)
3535 , fromSet
3636 , Common.fromIntMap
37+ , Common.verifyIntMap
38+ , fromTraversable
39+ , fromTraversableWith
3740 , fromTraversableWithKey
3841 , FromTraversableProof(..)
3942 -- * Insertion
4043 , insert
44+ , insertWith
45+ , insertWithKey
4146 , InsertProof(..)
4247 , reinsert
4348 , insertLookupWithKey
4449 -- * Deletion/Update
4550 , Common.delete
51+ , adjust'
4652 , adjust
4753 , adjustWithKey
54+ , update'
4855 , update
56+ , updateWithKey
4957 , updateLookupWithKey
5058 -- * Query
5159 , Common.lookup
@@ -61,21 +69,29 @@ module Data.IntMap.Strict.Refined
6169 , Common.disjoint
6270 , DisjointProof(..)
6371 -- * Combine
72+ , zipWith
6473 , zipWithKey
6574 , bind
75+ , Common.union
76+ , unionWith
6677 , unionWithKey
6778 , UnionProof(..)
6879 , Common.difference
6980 , DifferenceProof(..)
81+ , differenceWith
7082 , differenceWithKey
7183 , PartialDifferenceProof(..)
84+ , Common.intersection
85+ , intersectionWith
7286 , intersectionWithKey
7387 , IntersectionProof(..)
7488 -- * Traversal
89+ , map
7590 , mapWithKey
7691 , traverseWithKey
7792 , mapAccumLWithKey
7893 , mapAccumRWithKey
94+ , mapKeys
7995 , mapKeysWith
8096 , MapProof(..)
8197 , backpermuteKeys
@@ -93,12 +109,19 @@ module Data.IntMap.Strict.Refined
93109 -- * Filter
94110 , Common.restrictKeys
95111 , Common.withoutKeys
112+ , Common.filter
113+ , Common.filterKeys
96114 , Common.filterWithKey
115+ , Common.partition
97116 , Common.partitionWithKey
98117 , PartitionProof(..)
118+ , Common.takeWhileAntitone
119+ , Common.dropWhileAntitone
99120 , Common.spanAntitone
100121 , PartialPartitionProof(..)
122+ , mapMaybe
101123 , mapMaybeWithKey
124+ , mapEither
102125 , mapEitherWithKey
103126 , Common.splitLookup
104127 , SplitProof(..)
@@ -129,7 +152,7 @@ import Data.Proxy
129152import Data.Reflection
130153import Data.Traversable
131154import Data.Type.Coercion
132−import Prelude hiding (lookup, null)
155+import Prelude hiding (lookup, map, null, zipWith)
133156import Refined
134157import Refined.Unsafe
135158
@@ -145,17 +168,52 @@ singleton k v = SomeIntMapWith (IntMap $ IntMap.singleton k v)
145168fromSet :: forall s a. KnownIntSet s => (Key s -> a) -> IntMap s a
146169fromSet f = IntMap $ IntMap.fromSet (f . unsafeKey) (reflect $ Proxy @s)
147170
148−-- | Create a map from an arbitrary traversable of key-value pairs.
171+-- | Create a map from an arbitrary traversable of key-value pairs. If a key is
172+-- repeated, the retained value is the last one in traversal order. If you're
173+-- looking for @fromList@, this is the function you want.
174+fromTraversable
175+ :: forall t a. Traversable t
176+ => t (Int, a) -> SomeIntMapWith (FromTraversableProof 'Int t Int) a
177+fromTraversable xs = SomeIntMapWith (IntMap m) $ FromTraversableProof proof
178+ where
179+ (m, proof) = mapAccumL
180+ (\s (k, v) -> let !s' = IntMap.insert k v s in (s', unsafeKey k))
181+ IntMap.empty
182+ xs
183+
184+-- | Create a map from an arbitrary traversable of key-value pairs, with a
185+-- function for combining values for repeated keys. The function is called as if
186+-- by 'foldl1', but flipped:
187+--
188+-- @
189+-- 'fromTraversableWith' f [(k, x1), (k, x2), (k, x3)]
190+-- = 'singleton' k (f x3 (f x2 x1))
191+-- @
192+fromTraversableWith
193+ :: forall t a. Traversable t
194+ => (a -> a -> a)
195+ -> t (Int, a)
196+ -> SomeIntMapWith (FromTraversableProof 'Int t Int) a
197+fromTraversableWith f xs
198+ = SomeIntMapWith (IntMap m) $ FromTraversableProof proof
199+ where
200+ (m, proof) = mapAccumL
201+ (\s (k, v) -> let !s' = IntMap.insertWith f k v s in (s', unsafeKey k))
202+ IntMap.empty
203+ xs
204+
205+-- | Create a map from an arbitrary traversable of key-value pairs. Like
206+-- 'fromTraversableWith', but the combining function has access to the key.
149207fromTraversableWithKey
150208 :: forall t a. Traversable t
151209 => (Int -> a -> a -> a)
152210 -> t (Int, a)
153211 -> SomeIntMapWith (FromTraversableProof 'Int t Int) a
154−fromTraversableWithKey f xs = SomeIntMapWith (IntMap m)
155− $ FromTraversableProof proof
212+fromTraversableWithKey f xs
213+ = SomeIntMapWith (IntMap m) $ FromTraversableProof proof
156214 where
157215 (m, proof) = mapAccumL
158− (\s (k, v) -> (IntMap.insertWithKey f k v s, unsafeKey k))
216+ (\s (k, v) -> let !s' = IntMap.insertWithKey f k v s in (s', unsafeKey k))
159217 IntMap.empty
160218 xs
161219
@@ -170,8 +228,39 @@ insert
170228insert k v (IntMap m) = SomeIntMapWith (IntMap $ IntMap.insert k v m)
171229 $ InsertProof (unsafeKey k) unsafeSubset
172230
231+-- | Insert a key-value pair into the map to obtain a potentially larger map,
232+-- guaranteed to contain the given key. If the key was already present, the
233+-- supplied function is used to combine the new value with the old (in that
234+-- order).
235+insertWith
236+ :: forall s a. (a -> a -> a)
237+ -> Int
238+ -> a
239+ -> IntMap s a
240+ -> SomeIntMapWith (InsertProof 'Int Int s) a
241+insertWith f k v (IntMap m) = SomeIntMapWith
242+ (IntMap $ IntMap.insertWith f k v m)
243+ $ InsertProof (unsafeKey k) unsafeSubset
244+
245+-- | Insert a key-value pair into the map to obtain a potentially larger map,
246+-- guaranteed to contain the given key. Like 'insertWith', but the combining
247+-- function has access to the key, which is guaranteed to be in the old map.
248+insertWithKey
249+ :: forall s a. (Key s -> a -> a -> a)
250+ -> Int
251+ -> a
252+ -> IntMap s a
253+ -> SomeIntMapWith (InsertProof 'Int Int s) a
254+insertWithKey f k v (IntMap m) = SomeIntMapWith
255+ (IntMap $ IntMap.insertWithKey (f . unsafeKey) k v m)
256+ $ InsertProof (unsafeKey k) unsafeSubset
257+
173258-- | Overwrite a key-value pair that is known to already be in the map. The set
174259-- of keys remains the same.
260+--
261+-- @
262+-- 'reinsert' k v = 'adjust (const v) k'
263+-- @
175264reinsert
176265 :: forall s a. Key s -> a -> IntMap s a -> IntMap s a
177266reinsert = gcoerceWith (unsafeCastKey @s) $ coerce $ IntMap.insert @a
@@ -190,10 +279,15 @@ insertLookupWithKey f k v (IntMap m)
190279 (v', !m') -> ((unsafeKey k,) <$> v',)
191280 $ SomeIntMapWith (IntMap m') $ InsertProof (unsafeKey k) unsafeSubset
192281
282+-- | If the given key is in the map, update the value at that key using the
283+-- given function. In any case, the set of keys remains the same.
284+adjust' :: forall s a. (a -> a) -> Int -> IntMap s a -> IntMap s a
285+adjust' = coerce $ IntMap.adjust @a
286+
193287-- | Update the value at a specific key known the be in the map using the given
194288-- function. The set of keys remains the same.
195289adjust :: forall s a. (a -> a) -> Key s -> IntMap s a -> IntMap s a
196−adjust = gcoerceWith (unsafeCastKey @s) $ coerce $ IntMap.adjust @a
290+adjust = gcoerceWith (unsafeCastKey @s) $ coerce $ adjust' @s @a
197291
198292-- | If the given key is in the map, update the associated value using the given
199293-- function with a proof that the key was in the map; otherwise return the map
@@ -203,6 +297,16 @@ adjustWithKey
203297adjustWithKey = gcoerceWith (unsafeCastKey @s) $ coerce
204298 $ IntMap.adjustWithKey @a
205299
300+-- | If a key is present in the map, update its value or delete it using the
301+-- given function, returning a potentially smaller map.
302+update'
303+ :: forall s a. (a -> Maybe a)
304+ -> Int
305+ -> IntMap s a
306+ -> SomeIntMapWith (SupersetProof 'Int s) a
307+update' f k (IntMap m) = SomeIntMapWith (IntMap $ IntMap.update f k m)
308+ $ SupersetProof unsafeSubset
309+
206310-- | Update or delete a key known to be in the map using the given function,
207311-- returning a potentially smaller map.
208312update
@@ -210,7 +314,18 @@ update
210314 -> Key s
211315 -> IntMap s a
212316 -> SomeIntMapWith (SupersetProof 'Int s) a
213−update f k (IntMap m) = SomeIntMapWith (IntMap $ IntMap.update f (unrefine k) m)
317+update = gcoerceWith (unsafeCastKey @s) $ coerce $ update' @s @a
318+
319+-- | If a key is present in the map, update its value or delete it using the
320+-- given function with a proof that the key was in the map, returning a
321+-- potentially smaller map.
322+updateWithKey
323+ :: forall s a. (Key s -> a -> Maybe a)
324+ -> Int
325+ -> IntMap s a
326+ -> SomeIntMapWith (SupersetProof 'Int s) a
327+updateWithKey f k (IntMap m) = SomeIntMapWith
328+ (IntMap $ IntMap.updateWithKey (f . unsafeKey) k m)
214329 $ SupersetProof unsafeSubset
215330
216331-- | If the given key is in the map, update or delete it using the given
@@ -229,6 +344,28 @@ updateLookupWithKey f k (IntMap m)
229344
230345-- | Given two maps proven to have the same keys, for each key apply the
231346-- function to the associated values, to obtain a new map with the same keys.
347+zipWith
348+ :: forall s a b c. (a -> b -> c)
349+ -> IntMap s a
350+ -> IntMap s b
351+ -> IntMap s c
352+zipWith f (IntMap m1) (IntMap m2) = IntMap
353+ $ IntMap.mergeWithKey (\_ x y -> Just $ f x y)
354+ (\m -> if IntMap.null m
355+ then IntMap.empty
356+ else
357+ error "zipWith: bug: Data.IntMap.Strict.Refined has been subverted")
358+ (\m -> if IntMap.null m
359+ then IntMap.empty
360+ else
361+ error "zipWith: bug: Data.IntMap.Strict.Refined has been subverted")
362+ -- ^ Work around https://github.com/haskell/containers/issues/979
363+ m1
364+ m2
365+
366+-- | Given two maps proven to have the same keys, for each key apply the
367+-- function to the associated values and the key, to obtain a new map with the
368+-- same keys.
232369zipWithKey
233370 :: forall s a b c. (Key s -> a -> b -> c)
234371 -> IntMap s a
@@ -248,6 +385,17 @@ zipWithKey f (IntMap m1) (IntMap m2) = IntMap
248385 m1
249386 m2
250387
388+-- | Return the union of two maps, with a given combining function for keys that
389+-- exist in both maps simultaneously.
390+unionWith
391+ :: forall s t a. (a -> a -> a)
392+ -> IntMap s a
393+ -> IntMap t a
394+ -> SomeIntMapWith (UnionProof 'Int s t) a
395+unionWith f (IntMap m1) (IntMap m2) = SomeIntMapWith
396+ (IntMap $ IntMap.unionWith f m1 m2)
397+ $ UnionProof unsafeSubset unsafeSubsetWith2
398+
251399-- | Return the union of two maps, with a given combining function for keys that
252400-- exist in both maps simultaneously.
253401--
@@ -262,8 +410,19 @@ unionWithKey f (IntMap m1) (IntMap m2)
262410 = SomeIntMapWith (IntMap $ IntMap.unionWithKey (f . reallyUnsafeRefine) m1 m2)
263411 $ UnionProof unsafeSubset unsafeSubsetWith2
264412
265−-- | For keys that appear in both maps, the given function decides whether the
266−-- key is removed from the first map.
413+-- | Return the first map, but for keys that appear in both maps, the given
414+-- function decides whether the key is removed.
415+differenceWith
416+ :: forall s t a b. (a -> b -> Maybe a)
417+ -> IntMap s a
418+ -> IntMap t b
419+ -> SomeIntMapWith (PartialDifferenceProof 'Int s t) a
420+differenceWith f (IntMap m1) (IntMap m2) = SomeIntMapWith
421+ (IntMap $ IntMap.differenceWith f m1 m2)
422+ $ PartialDifferenceProof unsafeSubset unsafeSubset
423+
424+-- | Return the first map, but for keys that appear in both maps, the given
425+-- function decides whether the key is removed.
267426--
268427-- You can use 'andLeft' and 'andRight' to obtain @'Key' s@ and @'Key' t@
269428-- respectively.
@@ -279,6 +438,16 @@ differenceWithKey f (IntMap m1) (IntMap m2) = SomeIntMapWith
279438 (IntMap $ IntMap.differenceWithKey (f . reallyUnsafeRefine) m1 m2)
280439 $ PartialDifferenceProof unsafeSubset unsafeSubset
281440
441+-- | Return the intersection of two maps with the given combining function.
442+intersectionWith
443+ :: forall s t a b c. (a -> b -> c)
444+ -> IntMap s a
445+ -> IntMap t b
446+ -> SomeIntMapWith (IntersectionProof 'Int s t) c
447+intersectionWith f (IntMap m1) (IntMap m2) = SomeIntMapWith
448+ (IntMap $ IntMap.intersectionWith f m1 m2)
449+ $ IntersectionProof unsafeSubset unsafeSubsetWith2
450+
282451-- | Return the intersection of two maps with the given combining function.
283452--
284453-- You can use 'andLeft' and 'andRight' to obtain @'Key' s@ and @'Key' t@
@@ -295,6 +464,10 @@ intersectionWithKey f (IntMap m1) (IntMap m2) = SomeIntMapWith
295464 (IntMap $ IntMap.intersectionWithKey (f . reallyUnsafeRefine) m1 m2)
296465 $ IntersectionProof unsafeSubset unsafeSubsetWith2
297466
467+-- | Apply a function to all values in a map. The set of keys remains the same.
468+map :: forall s a b. (a -> b) -> IntMap s a -> IntMap s b
469+map = coerce $ IntMap.map @a @b
470+
298471-- | Apply a function to all values in a map, together with their corresponding
299472-- keys, that are proven to be in the map. The set of keys remains the same.
300473mapWithKey :: forall s a b. (Key s -> a -> b) -> IntMap s a -> IntMap s b
@@ -328,6 +501,27 @@ mapAccumRWithKey
328501mapAccumRWithKey = gcoerceWith (unsafeCastKey @s) $ coerce
329502 $ IntMap.mapAccumRWithKey @a @b @c
330503
504+-- | @'mapKeys' f m@ applies @f@ to each key of @m@ and collects the results
505+-- into a new map. For keys that were mapped to the same new key, the value
506+-- corresponding to the greatest of the original keys is retained.
507+mapKeys
508+ :: forall s a. (Key s -> Int)
509+ -> IntMap s a
510+ -> SomeIntMapWith (MapProof 'Int s Int Int) a
511+mapKeys g (IntMap m)
512+ = SomeIntMapWith (IntMap $ IntMap.mapKeys (g . unsafeKey) m)
513+ $ MapProof (unsafeKey . g) \k2 ->
514+ case IntMap.lookup (unrefine k2) backMap of
515+ Nothing -> error
516+ "mapKeys: bug: Data.IntMap.Strict.Refined has been subverted"
517+ Just k1 -> k1
518+ where
519+ ~backMap = IntMap.fromList
520+ [ (k2, unsafeKey k1)
521+ | k1 <- IntMap.keys m
522+ , let !k2 = g $ unsafeKey k1
523+ ]
524+
331525-- | @'mapKeysWith' c f m@ applies @f@ to each key of @m@ and collects the
332526-- results into a new map. For keys that were mapped to the same new key, @c@
333527-- acts as the combining function for corresponding values.
@@ -350,6 +544,15 @@ mapKeysWith f g (IntMap m)
350544 , let !k2 = g $ unsafeKey k1
351545 ]
352546
547+-- | Apply a function to all values in a map and collect only the 'Just'
548+-- results, returning a potentially smaller map.
549+mapMaybe
550+ :: forall s a b. (a -> Maybe b)
551+ -> IntMap s a
552+ -> SomeIntMapWith (SupersetProof 'Int s) b
553+mapMaybe f (IntMap m) = SomeIntMapWith (IntMap $ IntMap.mapMaybe f m)
554+ $ SupersetProof unsafeSubset
555+
353556-- | Apply a function to all values in a map, together with their corresponding
354557-- keys, and collect only the 'Just' results, returning a potentially smaller
355558-- map.
@@ -361,6 +564,23 @@ mapMaybeWithKey f (IntMap m)
361564 = SomeIntMapWith (IntMap $ IntMap.mapMaybeWithKey (f . unsafeKey) m)
362565 $ SupersetProof unsafeSubset
363566
567+-- | Apply a function to all values in a map and collect the 'Left' and 'Right'
568+-- results into separate (disjoint) maps.
569+mapEither
570+ :: forall s a b c. (a -> Either b c)
571+ -> IntMap s a
572+ -> Some2IntMapWith (PartitionProof 'Int s Int) b c
573+mapEither p (IntMap m)
574+ = case IntMap.mapEither p m of
575+ (m1, m2) -> Some2IntMapWith (IntMap m1) (IntMap m2) $ PartitionProof
576+ do \k -> case IntMap.lookup (unrefine k) m of
577+ Nothing -> error
578+ "mapEither: bug: Data.IntMap.Refined has been subverted"
579+ Just x -> case p x of
580+ Left _ -> Left $ unsafeKey $ unrefine k
581+ Right _ -> Right $ unsafeKey $ unrefine k
582+ unsafeSubset unsafeSubsetWith2 \f g -> unsafeSubsetWith2 f g
583+
364584-- | Apply a function to all values in a map, together with their corresponding
365585-- keys, and collect the 'Left' and 'Right' results into separate (disjoint)
366586-- maps.