@@ -0,0 +1,515 @@
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE UndecidableInstances #-}
3+module Data.Map.Common.Refined where
4+
5+import Control.Monad.Reader
6+import Control.DeepSeq
7+import Data.Coerce
8+import Data.Constraint (Dict(..))
9+import Data.Container.Refined.Proofs
10+import Data.Container.Refined.Unsafe
11+import Data.Distributive
12+import Data.Foldable.WithIndex
13+import Data.Functor.Rep
14+import Data.Functor.WithIndex
15+import qualified Data.Hashable as Hashable
16+import qualified Data.Map as Map
17+import Data.Proxy
18+import Data.Reflection
19+import Data.Traversable.WithIndex
20+import Data.Type.Coercion
21+import Data.Type.Equality ((:~:)(..))
22+import Refined
23+import Refined.Unsafe
24+import Unsafe.Coerce
25+
26+#if MIN_VERSION_containers(0, 6, 2)
27+#elif MIN_VERSION_containers(0, 5, 8)
28+import Data.Functor.Const (Const(..))
29+import Data.Monoid (Any(..))
30+import qualified Data.Map.Merge.Lazy as Map
31+#else
32+import qualified Data.List as List
33+import qualified Data.Map.Strict as MapStrict
34+#endif
35+
36+
37+-- | A wrapper around a regular 'Data.Map.Map' with a type parameter @s@
38+-- identifying the set of keys present in the map.
39+--
40+-- A key of type @k@ may not be present in the map, but a @'Key' s k@ is
41+-- guaranteed to be present (if the @s@ parameters match). Thus the map is
42+-- isomorphic to a (total) function @'Key' s k -> a@, which motivates many of
43+-- the instances below.
44+--
45+-- A 'Map' always knows its set of keys, so given @'Map' s k a@ we can always
46+-- derive @'KnownSet' s k@ by pattern matching on the 'Dict' returned by
47+-- 'keysSet'.
48+newtype Map s k a = Map (Map.Map k a)
49+ deriving newtype (Eq, Ord, Show, Functor, Foldable, NFData)
50+#if MIN_VERSION_hashable(1, 3, 4)
51+ deriving newtype (Hashable.Hashable)
52+#endif
53+ deriving stock (Traversable)
54+type role Map nominal nominal representational
55+
56+-- | Convert to a regular 'Data.Map.Map', forgetting its set of keys.
57+toMap :: forall s k a. Map s k a -> Map.Map k a
58+toMap (Map m) = m
59+
60+-- | @'Key' s k@ is a key of type @k@ that has been verified to be an element
61+-- of the set @s@, and thus verified to be present in all @'Map' s k@ maps.
62+--
63+-- Thus, @'Key' s k@ is a \"refinement\" type of @k@, and this library
64+-- integrates with an implementation of refimenement types in "Refined", so
65+-- the machinery from there can be used to manipulate 'Key's (however see
66+-- 'Data.Set.Refined.revealPredicate').
67+--
68+-- The underlying @k@ value can be obtained with 'unrefine'. A @k@ can be
69+-- validated into an @'Key' s k@ with 'member'.
70+type Key s = Refined (InSet 'Regular s)
71+
72+unsafeCastKey :: forall s k. Coercion k (Key s k)
73+unsafeCastKey = reallyUnsafeUnderlyingRefined
74+
75+unsafeKey :: k -> Key s k
76+unsafeKey = coerceWith unsafeCastKey
77+
78+-- | An existential wrapper for a 'Map' with an as-yet-unknown set of keys.
79+-- Pattern maching on it gives you a way to refer to the set (the parameter
80+-- @s@), e.g.
81+--
82+-- @
83+-- case 'fromMap' ... of
84+-- 'SomeMap' \@s m -> doSomethingWith \@s
85+--
86+-- case 'fromMap' ... of
87+-- 'SomeMap' (m :: 'Map' s k a) -> doSomethingWith \@s
88+-- @
89+data SomeMap k a where
90+ SomeMap :: forall s k a. !(Map s k a) -> SomeMap k a
91+
92+-- | Apply a map with an unknown set of keys to a continuation that can accept
93+-- a map with any set of keys. This gives you a way to refer to the set (the
94+-- parameter @s@), e.g.:
95+--
96+-- @
97+-- 'withMap' ('fromMap' ...) $ \(m :: 'Map' s k a) -> doSomethingWith \@s
98+-- @
99+withMap :: forall k a r. SomeMap k a -> (forall s. Map s k a -> r) -> r
100+withMap (SomeMap m) k = k m
101+
102+-- | Construct a map from a regular 'Data.Map.Map'.
103+fromMap :: forall k a. Map.Map k a -> SomeMap k a
104+fromMap m = SomeMap (Map m)
105+
106+-- | An existential wrapper for a 'Map' with an as-yet-unknown set of keys,
107+-- together with a proof of some fact @p@ about the set. Pattern matching on it
108+-- gives you a way to refer to the set (the parameter @s@). Functions that
109+-- change the set of keys in a map will return the map in this way, together
110+-- with a proof that somehow relates the keys set to the function's inputs.
111+data SomeMapWith p k a where
112+ SomeMapWith :: forall s k a p. !(Map s k a) -> !(p s) -> SomeMapWith p k a
113+
114+-- | Apply a map with proof for an unknown set of keys to a continuation that
115+-- can accept a map with any set of keys satisfying the proof. This gives you a
116+-- way to refer to the set (the parameter @s@).
117+withMapWith
118+ :: forall k a r p. SomeMapWith p k a -> (forall s. Map s k a -> p s -> r) -> r
119+withMapWith (SomeMapWith m p) k = k m p
120+
121+-- | An existential wrapper for a pair of maps with as-yet-unknown sets of keys,
122+-- together with a proof of some fact @p@ relating them.
123+data Some2MapWith p k a b where
124+ Some2MapWith
125+ :: forall s t k a b p. !(Map s k a)
126+ -> !(Map t k b)
127+ -> !(p s t)
128+ -> Some2MapWith p k a b
129+
130+-- | Apply a pair of maps with proof for unknown sets of keys to a continuation
131+-- that can accept any pair of maps with any sets of keys satisfying the proof.
132+-- This gives you a way to refer to the sets (the parameters @s@ and @t@).
133+with2MapWith
134+ :: forall k a b r p. Some2MapWith p k a b
135+ -> (forall s t. Map s k a -> Map t k b -> p s t -> r)
136+ -> r
137+with2MapWith (Some2MapWith m1 m2 p) k = k m1 m2 p
138+
139+-- | An empty map.
140+empty :: forall k a. SomeMapWith (EmptyProof 'Regular) k a
141+empty = SomeMapWith (Map Map.empty) $ EmptyProof unsafeSubset
142+
143+-- | Create a map from a set of keys, and a function that for each key computes
144+-- the corresponding value.
145+fromSet :: forall s k a. KnownSet s k => (Key s k -> a) -> Map s k a
146+fromSet f = Map $ Map.fromSet (f . unsafeKey) (reflect $ Proxy @s)
147+
148+-- | Delete a key and its value from the map if present, returning a potentially
149+-- smaller map.
150+delete
151+ :: forall s k a. Ord k
152+ => k -> Map s k a -> SomeMapWith (SupersetProof 'Regular s) k a
153+delete k (Map m) = SomeMapWith (Map $ Map.delete k m)
154+ $ SupersetProof unsafeSubset
155+
156+-- | If the key is in the map, return the proof of this, and the associated
157+-- value; otherwise return 'Nothing'.
158+lookup :: forall s k a. Ord k => k -> Map s k a -> Maybe (Key s k, a)
159+lookup k (Map m) = (unsafeKey k,) <$> Map.lookup k m
160+
161+-- | Given a key that is proven to be in the map, return the associated value.
162+--
163+-- Unlike 'Data.Map.!' from "Data.Map", this function is total, as it is
164+-- impossible to obtain a @'Key' s k@ for a key that is not in the map
165+-- @'Map' s k a@.
166+(!) :: forall s k a. Ord k => Map s k a -> Key s k -> a
167+(!) (Map m) k = case Map.lookup (unrefine k) m of
168+ Nothing -> error "(!): bug: Data.Map.Refined has been subverted"
169+ Just x -> x
170+
171+-- | If a key is in the map, return the proof that it is.
172+member :: forall s k a. Ord k => k -> Map s k a -> Maybe (Key s k)
173+member k (Map m)
174+ | k `Map.member` m = Just (unsafeKey k)
175+ | otherwise = Nothing
176+
177+-- | Find the largest key smaller than the given one, and return the
178+-- associated key-value pair.
179+lookupLT :: forall s k a. Ord k => k -> Map s k a -> Maybe (Key s k, a)
180+lookupLT = gcoerceWith (unsafeCastKey @s @k) $ coerce $ Map.lookupLT @k @a
181+
182+-- | Find the smallest key greater than the given one, and return the
183+-- associated key-value pair.
184+lookupGT :: forall s k a. Ord k => k -> Map s k a -> Maybe (Key s k, a)
185+lookupGT = gcoerceWith (unsafeCastKey @s @k) $ coerce $ Map.lookupGT @k @a
186+
187+-- | Find the largest key smaller or equal to the given one, and return the
188+-- associated key-value pair.
189+lookupLE :: forall s k a. Ord k => k -> Map s k a -> Maybe (Key s k, a)
190+lookupLE = gcoerceWith (unsafeCastKey @s @k) $ coerce $ Map.lookupLE @k @a
191+
192+-- | Find the smallest key greater or equal to the given one, and return the
193+-- associated key-value pair.
194+lookupGE :: forall s k a. Ord k => k -> Map s k a -> Maybe (Key s k, a)
195+lookupGE = gcoerceWith (unsafeCastKey @s @k) $ coerce $ Map.lookupGE @k @a
196+
197+-- | If a map is empty, return a proof that it is.
198+null :: forall s k a. Map s k a -> Maybe (EmptyProof 'Regular s)
199+null (Map m)
200+ | Map.null m = Just $ EmptyProof unsafeSubset
201+ | otherwise = Nothing
202+
203+-- | If all keys of the first map are also present in the second map, and the
204+-- given function returns 'True' for their associated values, return a proof
205+-- that the keys form a subset.
206+isSubmapOfBy
207+ :: forall s t k a b. Ord k
208+ => (a -> b -> Bool)
209+ -> Map s k a
210+ -> Map t k b
211+ -> Maybe (SubsetProof 'Regular s t)
212+isSubmapOfBy f (Map m1) (Map m2)
213+ | Map.isSubmapOfBy f m1 m2 = Just $ SubsetProof unsafeSubset
214+ | otherwise = Nothing
215+
216+-- | If two maps are disjoint (i.e. their intersection is empty), return a proof
217+-- of that.
218+disjoint
219+ :: forall s t k a b. Ord k
220+ => Map s k a -> Map t k b -> Maybe (DisjointProof 'Regular s t)
221+disjoint (Map m1) (Map m2)
222+#if MIN_VERSION_containers(0, 6, 2)
223+ | Map.disjoint m1 m2
224+#elif MIN_VERSION_containers(0, 5, 8)
225+ | Const (Any False) <- Map.mergeA
226+ (Map.traverseMissing \_ _ -> Const mempty)
227+ (Map.traverseMissing \_ _ -> Const mempty)
228+ (Map.zipWithAMatched \_ _ _ -> Const $ Any True)
229+ m1
230+ m2
231+#else
232+ | Map.null $ MapStrict.intersectionWith (\_ _ -> ()) m1 m2
233+#endif
234+ = Just $ DisjointProof \f g -> unsafeSubsetWith2 f g
235+ | otherwise = Nothing
236+
237+-- | Given two maps proven to have the same keys, for each key apply the
238+-- function to the associated values, to obtain a new map with the same keys.
239+zipWithKey
240+ :: forall s k a b c. Ord k
241+ => (Key s k -> a -> b -> c) -> Map s k a -> Map s k b -> Map s k c
242+zipWithKey f (Map m1) (Map m2) = Map
243+ $ Map.mergeWithKey (\k x y -> Just $ f (unsafeKey k) x y)
244+ (error "zipWithKey: bug: Data.Map.Refined has been subverted")
245+ (error "zipWithKey: bug: Data.Map.Refined has been subverted")
246+ m1
247+ m2
248+
249+-- | Remove the keys that appear in the second map from the first map.
250+difference
251+ :: forall s t k a b. Ord k
252+ => Map s k a -> Map t k b -> SomeMapWith (DifferenceProof 'Regular s t) k a
253+difference (Map m1) (Map m2) = SomeMapWith (Map $ Map.difference m1 m2)
254+ $ DifferenceProof unsafeSubset (\f g -> unsafeSubsetWith2 f g) unsafeSubset
255+
256+-- | Apply a function to all values in a map, together with their corresponding
257+-- keys, that are proven to be in the map. The set of keys remains the same.
258+mapWithKey :: forall s k a b. (Key s k -> a -> b) -> Map s k a -> Map s k b
259+mapWithKey = gcoerceWith (unsafeCastKey @s @k) $ coerce
260+ $ Map.mapWithKey @k @a @b
261+
262+-- | Map an 'Applicative' transformation in ascending order of keys, with access
263+-- to each value's corresponding key and a proof that it is in the map. The set
264+-- of keys remains unchanged.
265+traverseWithKey
266+ :: forall s f k a b. Applicative f
267+ => (Key s k -> a -> f b) -> Map s k a -> f (Map s k b)
268+traverseWithKey f (Map m) = Map <$> Map.traverseWithKey (f . unsafeKey) m
269+
270+-- | Map each key-value pair of a map into a monoid (with proof that the key was
271+-- in the map), and combine the results using '<>'.
272+foldMapWithKey
273+ :: forall s k a m. Monoid m => (Key s k -> a -> m) -> Map s k a -> m
274+foldMapWithKey = gcoerceWith (unsafeCastKey @s @k) $ coerce
275+ $ Map.foldMapWithKey @m @k @a
276+
277+-- | Right associative fold with a lazy accumulator.
278+foldrWithKey :: forall s k a b. (Key s k -> a -> b -> b) -> b -> Map s k a -> b
279+foldrWithKey = gcoerceWith (unsafeCastKey @s @k) $ coerce
280+ $ Map.foldrWithKey @k @a @b
281+
282+-- | Left associative fold with a lazy accumulator.
283+foldlWithKey :: forall s k a b. (b -> Key s k -> a -> b) -> b -> Map s k a -> b
284+foldlWithKey = gcoerceWith (unsafeCastKey @s @k) $ coerce
285+ $ Map.foldlWithKey @b @k @a
286+
287+-- | Right associative fold with a strict accumulator.
288+foldrWithKey' :: forall s k a b. (Key s k -> a -> b -> b) -> b -> Map s k a -> b
289+foldrWithKey' = gcoerceWith (unsafeCastKey @s @k) $ coerce
290+ $ Map.foldrWithKey' @k @a @b
291+
292+-- | Left associative fold with a strict accumulator.
293+foldlWithKey' :: forall s k a b. (b -> Key s k -> a -> b) -> b -> Map s k a -> b
294+foldlWithKey' = gcoerceWith (unsafeCastKey @s @k) $ coerce
295+ $ Map.foldlWithKey' @b @k @a
296+
297+-- | Return the set of keys in the map, with the contents of the set still
298+-- tracked by the @s@ parameter. See "Data.Set.Refined".
299+keysSet :: forall s k a. Map s k a -> Set s k
300+keysSet (Map m) = reify (Map.keysSet m)
301+ \(_ :: Proxy s') -> case unsafeCoerce Refl :: s :~: s' of
302+ Refl -> Dict
303+
304+-- | Convert to a list of key-value pairs in ascending order of keys.
305+toList :: forall s k a. Map s k a -> [(Key s k, a)]
306+toList = gcoerceWith (unsafeCastKey @s @k) $ coerce $ Map.toAscList @k @a
307+
308+-- | Convert to a list of key-value pairs in descending order of keys.
309+toDescList :: forall s k a. Map s k a -> [(Key s k, a)]
310+toDescList = gcoerceWith (unsafeCastKey @s @k) $ coerce $ Map.toDescList @k @a
311+
312+-- | Retain only the key-value pairs that satisfy the predicate, returning a
313+-- potentially smaller map.
314+filterWithKey
315+ :: forall s k a. (Key s k -> a -> Bool)
316+ -> Map s k a
317+ -> SomeMapWith (SupersetProof 'Regular s) k a
318+filterWithKey p (Map m)
319+ = SomeMapWith (Map $ Map.filterWithKey (p . unsafeKey) m)
320+ $ SupersetProof unsafeSubset
321+
322+-- | Restrict a map to only those keys that are elements of @t@.
323+restrictKeys
324+ :: forall s t k a. (Ord k, KnownSet t k)
325+ => Map s k a -> SomeMapWith (IntersectionProof 'Regular s t) k a
326+restrictKeys (Map m) = SomeMapWith
327+#if MIN_VERSION_containers(0, 5, 8)
328+ (Map $ Map.restrictKeys m $ reflect $ Proxy @t)
329+#else
330+ (Map $ Map.intersectionWith const m $ Map.fromSet id $ reflect $ Proxy @t)
331+#endif
332+ $ IntersectionProof unsafeSubset unsafeSubsetWith2
333+
334+-- | Remove all keys that are elements of @t@ from the map.
335+withoutKeys
336+ :: forall s t k a. (Ord k, KnownSet t k)
337+ => Map s k a -> SomeMapWith (DifferenceProof 'Regular s t) k a
338+withoutKeys (Map m) = SomeMapWith
339+#if MIN_VERSION_containers(0, 5, 8)
340+ (Map $ Map.withoutKeys m $ reflect $ Proxy @t)
341+#else
342+ (Map $ Map.difference m $ Map.fromSet id $ reflect $ Proxy @t)
343+#endif
344+ $ DifferenceProof unsafeSubset (\f g -> unsafeSubsetWith2 f g) unsafeSubset
345+
346+-- | Partition a map into two disjoint submaps: those whose key-value pairs
347+-- satisfy the predicate, and those whose don't.
348+partitionWithKey
349+ :: forall s k a. Ord k -- TODO: this is only used in the proof
350+ => (Key s k -> a -> Bool)
351+ -> Map s k a
352+ -> Some2MapWith (PartitionProof 'Regular s k) k a a
353+partitionWithKey p (Map m) = case Map.partitionWithKey (p . unsafeKey) m of
354+ (m1, m2) -> Some2MapWith (Map m1) (Map m2) $ PartitionProof
355+ do \k -> case Map.lookup (unrefine k) m of
356+ Nothing
357+ -> error "partitionWithKey: bug: Data.Map.Refined has been subverted"
358+ Just x -> if p k x
359+ then Left $ unsafeKey $ unrefine k
360+ else Right $ unsafeKey $ unrefine k
361+ unsafeSubset unsafeSubsetWith2 \f g -> unsafeSubsetWith2 f g
362+
363+-- | Divide a map into two disjoint submaps at a point where the predicate on
364+-- the keys stops holding.
365+--
366+-- If @p@ is antitone ( \(\forall x y, x < y \implies p(x) \ge p(y)\) ), then
367+-- this point is uniquely defined. If @p@ is not antitone, a splitting point is
368+-- chosen in an unspecified way.
369+spanAntitone
370+ :: forall s k a. (Key s k -> Bool)
371+ -> Map s k a
372+ -> Some2MapWith (PartialPartitionProof 'Regular s) k a a
373+spanAntitone p (Map m) =
374+#if MIN_VERSION_containers(0, 5, 8)
375+ case Map.spanAntitone (p . unsafeKey) m of
376+ (m1, m2)
377+#else
378+ case List.span (p . unsafeKey . fst) $ Map.toAscList m of
379+ (xs1, xs2)
380+ | let m1 = Map.fromDistinctAscList xs1
381+ , let m2 = Map.fromDistinctAscList xs2
382+#endif
383+ -> Some2MapWith (Map m1) (Map m2) $ PartialPartitionProof
384+ unsafeSubset unsafeSubsetWith2 \f g -> unsafeSubsetWith2 f g
385+
386+-- | Return two disjoint submaps: those whose keys are less than the given key,
387+-- and those whose keys are greater than the given key. If the key was in the
388+-- map, also return the associated value and the proof that it was in the map.
389+splitLookup
390+ :: forall s k a. Ord k
391+ => k -> Map s k a -> Some2MapWith (SplitProof 'Regular s (Key s k, a)) k a a
392+splitLookup k (Map m) = case Map.splitLookup k m of
393+ (!m1, v, !m2) -> Some2MapWith (Map m1) (Map m2) $ SplitProof
394+ ((unsafeKey k,) <$> v) unsafeSubset \f g -> unsafeSubsetWith2 f g
395+
396+-- | Retrieves the key-value pair corresponding to the smallest key of the map,
397+-- and the map with that pair removed; or a proof that the map was empty.
398+minViewWithKey
399+ :: forall s k a. Map s k a
400+ -> Either
401+ (EmptyProof 'Regular s)
402+ ((Key s k, a), SomeMapWith (SupersetProof 'Regular s) k a)
403+minViewWithKey (Map m) = case Map.minViewWithKey m of
404+ Nothing -> Left $ EmptyProof unsafeSubset
405+ Just (kv, m') -> Right $ (gcoerceWith (unsafeCastKey @s @k) $ coerce kv,)
406+ $ SomeMapWith (Map m') $ SupersetProof unsafeSubset
407+
408+-- | Retrieves the key-value pair corresponding to the greatest key of the map,
409+-- and the map with that pair removed; or a proof that the map was empty.
410+maxViewWithKey
411+ :: forall s k a. Map s k a
412+ -> Either
413+ (EmptyProof 'Regular s)
414+ ((Key s k, a), SomeMapWith (SupersetProof 'Regular s) k a)
415+maxViewWithKey (Map m) = case Map.maxViewWithKey m of
416+ Nothing -> Left $ EmptyProof unsafeSubset
417+ Just (kv, m') -> Right $ (gcoerceWith (unsafeCastKey @s @k) $ coerce kv,)
418+ $ SomeMapWith (Map m') $ SupersetProof unsafeSubset
419+
420+-- | If elements of @s@ can be weakened to elements of @t@ and vice versa, then
421+-- @s@ and @t@ actually stand for the same set and @'Key' s@ can be safely
422+-- interconverted with @'Key' t@.
423+--
424+-- The requirement that the weakenings are natural transformations ensures that
425+-- they don't actually alter the keys. To build these you can compose ':->''s
426+-- from proofs returned by functions in this module, or "Refined" functions like
427+-- 'andLeft' or 'leftOr'.
428+castKey
429+ :: forall s t k. (forall x. Key s x -> Key t x)
430+ -> (forall x. Key t x -> Key s x)
431+ -> Coercion (Key s k) (Key t k)
432+castKey = castRefined
433+
434+-- | If keys can be interconverted (e.g. as proved by 'castKey'), then the maps
435+-- can be interconverted too. For example, 'zipWithKey' can be implemented via
436+-- 'Data.Map.Refined.intersectionWithKey' by proving that the set of keys
437+-- remains unchanged:
438+--
439+-- @
440+-- 'zipWithKey'
441+-- :: forall s k a b c. 'Ord' k
442+-- => ('Key' s k -> a -> b -> c) -> 'Map' s k a -> 'Map' s k b -> 'Map' s k c
443+-- 'zipWithKey' f m1 m2
444+-- | v'SomeMapWith' @r m proof <- 'Data.Map.Refined.intersectionWithKey' (f . 'andLeft') m1 m2
445+-- , v'IntersectionProof' p1 p2 <- proof
446+-- , ( v'Coercion' :: t'Coercion' ('Map' r k c) ('Map' s k c))
447+-- <- app $ 'cast' $ 'castKey' ('andLeft' . p1) (p2 'id' 'id')
448+-- = 'coerce' m
449+-- where
450+-- app :: t'Coercion' f g -> t'Coercion' (f x) (g x)
451+-- app v'Coercion' = v'Coercion'
452+-- @
453+cast
454+ :: forall s t k. (forall x. Coercion (Key s x) (Key t x))
455+ -> Coercion (Map s k) (Map t k)
456+cast Coercion = Coercion
457+
458+instance FunctorWithIndex (Key s k) (Map s k) where
459+ imap = mapWithKey
460+
461+instance FoldableWithIndex (Key s k) (Map s k) where
462+ ifoldMap = foldMapWithKey
463+
464+instance TraversableWithIndex (Key s k) (Map s k) where
465+ itraverse = traverseWithKey
466+
467+-- | Similar to the instance for functions -- zip corresponding keys. To use
468+-- '<*>'/'liftA2' without 'KnownSet' see 'zipWithKey'.
469+instance (Ord k, KnownSet s k) => Applicative (Map s k) where
470+ pure x = fromSet \_ -> x
471+ (<*>) = zipWithKey (const id)
472+
473+-- | @'bind' m f@ is a map that for each key @k :: 'Key' s k@, contains the
474+-- value @f (m '!' k) '!' k@, similar to @'>>='@ for functions.
475+bind :: forall s k a b. Ord k => Map s k a -> (a -> Map s k b) -> Map s k b
476+bind m f = mapWithKey (\k x -> f x ! k) m
477+
478+-- | Similar to the instance for functions. To use '>>=' without 'KnownSet' see
479+-- 'bind'.
480+instance (Ord k, KnownSet s k) => Monad (Map s k) where
481+ (>>=) = bind
482+
483+-- | Similar to the instance for functions. See also
484+-- 'Data.Map.Refined.backpermuteKeys'.
485+instance (Ord k, KnownSet s k) => MonadReader (Key s k) (Map s k) where
486+ ask = fromSet id
487+ local f m = mapWithKey (\k _ -> m ! f k) m
488+
489+-- | Append the values at the corresponding keys
490+instance (Ord k, Semigroup a) => Semigroup (Map s k a) where
491+ (<>) = zipWithKey (const (<>))
492+
493+instance (Ord k, KnownSet s k, Monoid a) => Monoid (Map s k a) where
494+ mempty = fromSet \_ -> mempty
495+
496+-- | Similar to the instance for functions
497+instance (Ord k, KnownSet s k) => Distributive (Map s k) where
498+ collect = collectRep
499+ distribute = distributeRep
500+
501+-- | Witness isomorphism with functions from @'Key' s k@
502+instance (Ord k, KnownSet s k) => Representable (Map s k) where
503+ type Rep (Map s k) = Key s k
504+ index = (!)
505+ tabulate = fromSet
506+
507+#if MIN_VERSION_hashable(1, 3, 4)
508+#else
509+instance (Hashable.Hashable a, Hashable.Hashable k)
510+ => Hashable.Hashable (Map s k a) where
511+ hashWithSalt s (Map m) = Map.foldlWithKey'
512+ (\s' k v -> Hashable.hashWithSalt (Hashable.hashWithSalt s' k) v)
513+ (Hashable.hashWithSalt s (Map.size m))
514+ m
515+#endif