git.iko.soy/monoidal-containers
on master help sign in
Merge pull request #41 from 3noch/eac@changelog

Use value's semigroup instance more consistently across functions

commit17f400fecd62a0a66b86060f6e35527c42635c0f authorAli Abrar <aliabrar@gmail.com> dateTue 30 Jul 2019, 20:11 (7 years ago) parent84e523d11b7917
3 files changed+48−10
Changelog.md+4−2 src/Data/Map/Monoidal.hs+22−4 src/Data/Map/Monoidal/Strict.hs+22−4
Changelog.md+4−2
@@ -2,12 +2,14 @@
22
33# Unreleased
44
5−* Added Data.IntMap.Monoidal and Data.IntMap.Monoidal.Strict, corresponding to Data.IntMap and Data.IntMap.Strict
5+ * Added Data.IntMap.Monoidal and Data.IntMap.Monoidal.Strict, corresponding to Data.IntMap and Data.IntMap.Strict
6+ * Make `fromList`, `insert`, and `mapKeys` from `Data.Map.Monoidal` and `Data.Map.Monoidal.Strict` require `Semigroup` on values to properly capture monoidal behavior instead of reverting to the left-biased semantics of `Data.Map`.
7+ * Support `these` 0.8.0
68
79# 0.4.0.0
810
911General changes:
10−
12+
1113 * Added support for `unordered-containers < 0.2.8`
1214 * Added many more functions in `Data.Map.[Strict.]Monoid`
1315
src/Data/Map/Monoidal.hs+22−4
@@ -323,8 +323,8 @@ empty :: forall k a. MonoidalMap k a
323323empty = coerce (M.empty :: M.Map k a)
324324{-# INLINE empty #-}
325325
326−insert :: forall k a. Ord k => k -> a -> MonoidalMap k a -> MonoidalMap k a
327−insert = coerce (M.insert :: k -> a -> M.Map k a -> M.Map k a)
326+insert :: forall k a. (Ord k, Semigroup a) => k -> a -> MonoidalMap k a -> MonoidalMap k a
327+insert = insertWith (<>)
328328{-# INLINE insert #-}
329329
330330insertWith :: forall k a. Ord k => (a -> a -> a) -> k -> a -> MonoidalMap k a -> MonoidalMap k a
@@ -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 #-}
src/Data/Map/Monoidal/Strict.hs+22−4
@@ -322,8 +322,8 @@ empty :: forall k a. MonoidalMap k a
322322empty = coerce (M.empty :: M.Map k a)
323323{-# INLINE empty #-}
324324
325−insert :: forall k a. Ord k => k -> a -> MonoidalMap k a -> MonoidalMap k a
326−insert = coerce (M.insert :: k -> a -> M.Map k a -> M.Map k a)
325+insert :: forall k a. (Ord k, Semigroup a) => k -> a -> MonoidalMap k a -> MonoidalMap k a
326+insert = insertWith (<>)
327327{-# INLINE insert #-}
328328
329329insertWith :: forall k a. Ord k => (a -> a -> a) -> k -> a -> MonoidalMap k a -> MonoidalMap k a
@@ -422,14 +422,32 @@ mapAccumRWithKey :: forall k a b c. (a -> k -> b -> (a, c)) -> a -> MonoidalMap
422422mapAccumRWithKey = coerce (M.mapAccumRWithKey :: (a -> k -> b -> (a, c)) -> a -> M.Map k b -> (a, M.Map k c))
423423{-# INLINE mapAccumRWithKey #-}
424424
425−mapKeys :: forall k1 k2 a. Ord k2 => (k1 -> k2) -> MonoidalMap k1 a -> MonoidalMap k2 a
426−mapKeys = coerce (M.mapKeys :: (k1 -> k2) -> M.Map k1 a -> M.Map k2 a)
425+mapKeys :: forall k1 k2 a. (Ord k2, Semigroup a) => (k1 -> k2) -> MonoidalMap k1 a -> MonoidalMap k2 a
426+mapKeys = mapKeysWith (<>)
427427{-# INLINE mapKeys #-}
428428
429429mapKeysWith :: forall k1 k2 a. Ord k2 => (a -> a -> a) -> (k1 -> k2) -> MonoidalMap k1 a -> MonoidalMap k2 a
430430mapKeysWith = coerce (M.mapKeysWith :: (a -> a -> a) -> (k1 -> k2) -> M.Map k1 a -> M.Map k2 a)
431431{-# INLINE mapKeysWith #-}
432432
433+-- | /O(n)/.
434+-- @'mapKeysMonotonic' f s == 'mapKeys' f s@, but works only when @f@
435+-- is strictly increasing (both monotonic and injective).
436+-- That is, for any values @x@ and @y@, if @x@ < @y@ then @f x@ < @f y@
437+-- and @f@ is injective (i.e. it never maps two input keys to the same output key).
438+-- /The precondition is not checked./
439+-- Semi-formally, we have:
440+--
441+-- > and [x < y ==> f x < f y | x <- ls, y <- ls]
442+-- > ==> mapKeysMonotonic f s == mapKeys f s
443+-- > where ls = keys s
444+--
445+-- This means that @f@ maps distinct original keys to distinct resulting keys.
446+-- This function has better performance than 'mapKeys'.
447+--
448+-- > mapKeysMonotonic (\ k -> k * 2) (fromList [(5,"a"), (3,"b")]) == fromList [(6, "b"), (10, "a")]
449+-- > valid (mapKeysMonotonic (\ k -> k * 2) (fromList [(5,"a"), (3,"b")])) == True
450+-- > valid (mapKeysMonotonic (\ _ -> 1) (fromList [(5,"a"), (3,"b")])) == False
433451mapKeysMonotonic :: forall k1 k2 a. (k1 -> k2) -> MonoidalMap k1 a -> MonoidalMap k2 a
434452mapKeysMonotonic = coerce (M.mapKeysMonotonic :: (k1 -> k2) -> M.Map k1 a -> M.Map k2 a)
435453{-# INLINE mapKeysMonotonic #-}