@@ -20,6 +20,7 @@ import qualified Data.Set as Set
2020import Data.Traversable.WithIndex
2121import Data.Type.Coercion
2222import Data.Type.Equality ((:~:)(..))
23+import Prelude hiding (zipWith)
2324import Refined
2425import Refined.Unsafe
2526import Unsafe.Coerce
@@ -109,7 +110,7 @@ data SomeMap k a where
109110-- parameter @s@), e.g.:
110111--
111112-- @
112−-- 'withMap' ('fromMap' ...) $ \(m :: 'Map' s k a) -> doSomethingWith \@s
113+-- 'withMap' ('fromMap' ...) $ \\(m :: 'Map' s k a) -> doSomethingWith \@s
113114-- @
114115withMap :: forall k a r. SomeMap k a -> (forall s. Map s k a -> r) -> r
115116withMap (SomeMap m) k = k m
@@ -259,17 +260,17 @@ disjoint (Map m1) (Map m2)
259260
260261-- | Given two maps proven to have the same keys, for each key apply the
261262-- function to the associated values, to obtain a new map with the same keys.
262−zipWithKey
263+zipWith
263264 :: forall s k a b c. Ord k
264− => (Key s k -> a -> b -> c) -> Map s k a -> Map s k b -> Map s k c
265−zipWithKey f (Map m1) (Map m2) = Map
266− $ Map.mergeWithKey (\k x y -> Just $ f (unsafeKey k) x y)
265+ => (a -> b -> c) -> Map s k a -> Map s k b -> Map s k c
266+zipWith f (Map m1) (Map m2) = Map
267+ $ Map.mergeWithKey (\_ x y -> Just $ f x y)
267268 (\m -> if Map.null m
268269 then Map.empty
269− else error "zipWithKey: bug: Data.Map.Refined has been subverted")
270+ else error "zipWith: bug: Data.Map.Refined has been subverted")
270271 (\m -> if Map.null m
271272 then Map.empty
272− else error "zipWithKey: bug: Data.Map.Refined has been subverted")
273+ else error "zipWith: bug: Data.Map.Refined has been subverted")
273274 -- ^ Work around https://github.com/haskell/containers/issues/979
274275 m1
275276 m2
@@ -293,6 +294,20 @@ difference
293294difference (Map m1) (Map m2) = SomeMapWith (Map $ Map.difference m1 m2)
294295 $ DifferenceProof unsafeSubset (\f g -> unsafeSubsetWith2 f g) unsafeSubset
295296
297+-- | Return the intersection of two maps, taking values from the first map.
298+--
299+-- @
300+-- 'intersection' = intersectionWith 'const'
301+-- @
302+intersection
303+ :: forall s t k a b. Ord k
304+ => Map s k a
305+ -> Map t k b
306+ -> SomeMapWith (IntersectionProof 'Regular s t) k a
307+intersection (Map m1) (Map m2)
308+ = SomeMapWith (Map $ Map.intersection m1 m2)
309+ $ IntersectionProof unsafeSubset unsafeSubsetWith2
310+
296311-- | Apply a function to all values in a map, together with their corresponding
297312-- keys, that are proven to be in the map. The set of keys remains the same.
298313mapWithKey :: forall s k a b. (Key s k -> a -> b) -> Map s k a -> Map s k b
@@ -349,6 +364,29 @@ toList = gcoerceWith (unsafeCastKey @s @k) $ coerce $ Map.toAscList @k @a
349364toDescList :: forall s k a. Map s k a -> [(Key s k, a)]
350365toDescList = gcoerceWith (unsafeCastKey @s @k) $ coerce $ Map.toDescList @k @a
351366
367+-- | Retain only the values that satisfy the predicate, returning a potentially
368+-- smaller map.
369+filter
370+ :: forall s k a. (a -> Bool)
371+ -> Map s k a
372+ -> SomeMapWith (SupersetProof 'Regular s) k a
373+filter p (Map m) = SomeMapWith (Map $ Map.filter p m)
374+ $ SupersetProof unsafeSubset
375+
376+-- | Retain only the keys that satisfy the predicate, returning a potentially
377+-- smaller map.
378+filterKeys
379+ :: forall s k a. (Key s k -> Bool)
380+ -> Map s k a
381+ -> SomeMapWith (SupersetProof 'Regular s) k a
382+filterKeys p (Map m) = SomeMapWith
383+#if MIN_VERSION_containers(0, 8, 0)
384+ (Map $ Map.filterKeys (p . unsafeKey) m)
385+#else
386+ (Map $ Map.filterWithKey (\k _ -> p (unsafeKey k)) m)
387+#endif
388+ $ SupersetProof unsafeSubset
389+
352390-- | Retain only the key-value pairs that satisfy the predicate, returning a
353391-- potentially smaller map.
354392filterWithKey
@@ -383,6 +421,22 @@ withoutKeys (Map m) = SomeMapWith
383421#endif
384422 $ DifferenceProof unsafeSubset (\f g -> unsafeSubsetWith2 f g) unsafeSubset
385423
424+-- | Partition a map into two disjoint submaps: those whose values satisfy the
425+-- predicate, and those whose don't.
426+partition
427+ :: forall s k a. Ord k -- TODO: this is only used in the proof
428+ => (a -> Bool)
429+ -> Map s k a
430+ -> Some2MapWith (PartitionProof 'Regular s k) k a a
431+partition p (Map m) = case Map.partition p m of
432+ (m1, m2) -> Some2MapWith (Map m1) (Map m2) $ PartitionProof
433+ do \k -> case Map.lookup (unrefine k) m of
434+ Nothing -> error "partition: bug: Data.Map.Refined has been subverted"
435+ Just x -> if p x
436+ then Left $ unsafeKey $ unrefine k
437+ else Right $ unsafeKey $ unrefine k
438+ unsafeSubset unsafeSubsetWith2 \f g -> unsafeSubsetWith2 f g
439+
386440-- | Partition a map into two disjoint submaps: those whose key-value pairs
387441-- satisfy the predicate, and those whose don't.
388442partitionWithKey
@@ -400,6 +454,43 @@ partitionWithKey p (Map m) = case Map.partitionWithKey (p . unsafeKey) m of
400454 else Right $ unsafeKey $ unrefine k
401455 unsafeSubset unsafeSubsetWith2 \f g -> unsafeSubsetWith2 f g
402456
457+-- | Take the a submap of keys up to a point where the predicate stops holding.
458+--
459+-- If @p@ is antitone ( \(\forall x y, x < y \implies p(x) \ge p(y)\) ), then
460+-- this point is uniquely defined. If @p@ is not antitone, a splitting point is
461+-- chosen in an unspecified way.
462+takeWhileAntitone
463+ :: forall s k a. (Key s k -> Bool)
464+ -> Map s k a
465+ -> SomeMapWith (SupersetProof 'Regular s) k a
466+takeWhileAntitone p (Map m) = SomeMapWith
467+#if MIN_VERSION_containers(0, 5, 8)
468+ (Map $ Map.takeWhileAntitone (p . unsafeKey) m)
469+#else
470+ (Map $ Map.fromDistinctAscList
471+ $ List.takeWhile (p . unsafeKey . fst) $ Map.toAscList m)
472+#endif
473+ $ SupersetProof unsafeSubset
474+
475+-- | Take the a submap of keys starting from a point where the predicate stops
476+-- holding.
477+--
478+-- If @p@ is antitone ( \(\forall x y, x < y \implies p(x) \ge p(y)\) ), then
479+-- this point is uniquely defined. If @p@ is not antitone, a splitting point is
480+-- chosen in an unspecified way.
481+dropWhileAntitone
482+ :: forall s k a. (Key s k -> Bool)
483+ -> Map s k a
484+ -> SomeMapWith (SupersetProof 'Regular s) k a
485+dropWhileAntitone p (Map m) = SomeMapWith
486+#if MIN_VERSION_containers(0, 5, 8)
487+ (Map $ Map.dropWhileAntitone (p . unsafeKey) m)
488+#else
489+ (Map $ Map.fromDistinctAscList
490+ $ List.dropWhile (p . unsafeKey . fst) $ Map.toAscList m)
491+#endif
492+ $ SupersetProof unsafeSubset
493+
403494-- | Divide a map into two disjoint submaps at a point where the predicate on
404495-- the keys stops holding.
405496--
@@ -472,15 +563,15 @@ castKey
472563castKey = castRefined
473564
474565-- | If keys can be interconverted (e.g. as proved by 'castKey'), then the maps
475−-- can be interconverted too. For example, 'zipWithKey' can be implemented via
476−-- 'Data.Map.Refined.intersectionWithKey' by proving that the set of keys
477−-- remains unchanged:
566+-- can be interconverted too. For example, 'Data.Map.Refined.zipWithKey' can be
567+-- implemented via 'Data.Map.Refined.intersectionWithKey' by proving that the
568+-- set of keys remains unchanged:
478569--
479570-- @
480−-- 'zipWithKey'
571+-- 'Data.Map.Refined.zipWithKey'
481572-- :: forall s k a b c. 'Ord' k
482573-- => ('Key' s k -> a -> b -> c) -> 'Map' s k a -> 'Map' s k b -> 'Map' s k c
483−-- 'zipWithKey' f m1 m2
574+-- 'Data.Map.Refined.zipWithKey' f m1 m2
484575-- | v'SomeMapWith' @r m proof <- 'Data.Map.Refined.intersectionWithKey' (f . 'andLeft') m1 m2
485576-- , v'IntersectionProof' p1 p2 <- proof
486577-- , ( v'Coercion' :: t'Coercion' ('Map' r k c) ('Map' s k c))
@@ -505,10 +596,10 @@ instance TraversableWithIndex (Key s k) (Map s k) where
505596 itraverse = traverseWithKey
506597
507598-- | Similar to the instance for functions -- zip corresponding keys. To use
508−-- '<*>'/'Control.Applicative.liftA2' without 'KnownSet' see 'zipWithKey'.
599+-- '<*>'/'Control.Applicative.liftA2' without 'KnownSet' see 'zipWith'.
509600instance (Ord k, KnownSet s k) => Applicative (Map s k) where
510601 pure x = fromSet \_ -> x
511− (<*>) = zipWithKey (const id)
602+ (<*>) = zipWith id
512603
513604-- | @'bind' m f@ is a map that for each key @k :: 'Key' s k@, contains the
514605-- value @f (m '!' k) '!' k@, similar to @'>>='@ for functions.
@@ -528,7 +619,7 @@ instance (Ord k, KnownSet s k) => MonadReader (Key s k) (Map s k) where
528619
529620-- | Append the values at the corresponding keys
530621instance (Ord k, Semigroup a) => Semigroup (Map s k a) where
531− (<>) = zipWithKey (const (<>))
622+ (<>) = zipWith (<>)
532623
533624instance (Ord k, KnownSet s k, Monoid a) => Monoid (Map s k a) where
534625 mempty = fromSet \_ -> mempty