@@ -423,14 +423,32 @@ mapAccumRWithKey :: forall k a b c. (a -> k -> b -> (a, c)) -> a -> MonoidalMap
423423mapAccumRWithKey = coerce (M.mapAccumRWithKey :: (a -> k -> b -> (a, c)) -> a -> M.Map k b -> (a, M.Map k c))
424424{-# INLINE mapAccumRWithKey #-}
425425
426−mapKeys :: forall k1 k2 a. Ord k2 => (k1 -> k2) -> MonoidalMap k1 a -> MonoidalMap k2 a
427−mapKeys = coerce (M.mapKeys :: (k1 -> k2) -> M.Map k1 a -> M.Map k2 a)
426+mapKeys :: forall k1 k2 a. (Ord k2, Semigroup a) => (k1 -> k2) -> MonoidalMap k1 a -> MonoidalMap k2 a
427+mapKeys = mapKeysWith (<>)
428428{-# INLINE mapKeys #-}
429429
430430mapKeysWith :: forall k1 k2 a. Ord k2 => (a -> a -> a) -> (k1 -> k2) -> MonoidalMap k1 a -> MonoidalMap k2 a
431431mapKeysWith = coerce (M.mapKeysWith :: (a -> a -> a) -> (k1 -> k2) -> M.Map k1 a -> M.Map k2 a)
432432{-# INLINE mapKeysWith #-}
433433
434+-- | /O(n)/.
435+-- @'mapKeysMonotonic' f s == 'mapKeys' f s@, but works only when @f@
436+-- is strictly increasing (both monotonic and injective).
437+-- That is, for any values @x@ and @y@, if @x@ < @y@ then @f x@ < @f y@
438+-- and @f@ is injective (i.e. it never maps two input keys to the same output key).
439+-- /The precondition is not checked./
440+-- Semi-formally, we have:
441+--
442+-- > and [x < y ==> f x < f y | x <- ls, y <- ls]
443+-- > ==> mapKeysMonotonic f s == mapKeys f s
444+-- > where ls = keys s
445+--
446+-- This means that @f@ maps distinct original keys to distinct resulting keys.
447+-- This function has better performance than 'mapKeys'.
448+--
449+-- > mapKeysMonotonic (\ k -> k * 2) (fromList [(5,"a"), (3,"b")]) == fromList [(6, "b"), (10, "a")]
450+-- > valid (mapKeysMonotonic (\ k -> k * 2) (fromList [(5,"a"), (3,"b")])) == True
451+-- > valid (mapKeysMonotonic (\ _ -> 1) (fromList [(5,"a"), (3,"b")])) == False
434452mapKeysMonotonic :: forall k1 k2 a. (k1 -> k2) -> MonoidalMap k1 a -> MonoidalMap k2 a
435453mapKeysMonotonic = coerce (M.mapKeysMonotonic :: (k1 -> k2) -> M.Map k1 a -> M.Map k2 a)
436454{-# INLINE mapKeysMonotonic #-}