@@ -23,15 +23,20 @@ module Data.HashMap.Monoidal
2323 , member
2424 , notMember
2525 , lookup
26+ , lookupM
2627 , elems
2728 , keys
29+ , delete
30+ , mapKeys
31+ , modify
32+ , modifyDef
2833 ) where
2934
3035import Prelude hiding (lookup)
36+import Data.Maybe (fromMaybe)
3137import Data.Monoid
3238import Data.Foldable (Foldable)
33−import Data.Traversable (Traversable)
34−import Control.Applicative (Applicative, pure)
39+import Control.Applicative (pure)
3540import Data.Data (Data)
3641import Data.Typeable (Typeable)
3742
@@ -96,9 +101,9 @@ instance Newtype (MonoidalHashMap k a) (M.HashMap k a) where
96101 {-# INLINE unpack #-}
97102
98103#if MIN_VERSION_base(4,7,0)
99−instance (Eq k, Hashable k) => IsList (MonoidalHashMap k a) where
104+instance (Eq k, Hashable k, Monoid a) => IsList (MonoidalHashMap k a) where
100105 type Item (MonoidalHashMap k a) = (k, a)
101− fromList = MM . M.fromList
106+ fromList = MM . M.fromListWith mappend
102107 {-# INLINE fromList #-}
103108 toList = M.toList . unpack
104109 {-# INLINE toList #-}
@@ -130,6 +135,12 @@ lookup :: (Eq k, Hashable k) => k -> MonoidalHashMap k v -> Maybe v
130135lookup k = M.lookup k . unpack
131136{-# INLINE lookup #-}
132137
138+-- | /O(log n)/ Return the value to which the specified key is mapped,
139+-- or mempty if this map contains no mapping for the key.
140+lookupM :: (Eq k, Hashable k, Monoid v) => k -> MonoidalHashMap k v -> v
141+lookupM k = fromMaybe mempty . M.lookup k . unpack
142+{-# INLINE lookupM #-}
143+
133144-- | /O(log n)/. Delete a key and its value from the map. When the key is not
134145-- a member of the map, the original map is returned.
135146delete :: (Eq k, Hashable k) => k -> MonoidalHashMap k a -> MonoidalHashMap k a
@@ -148,3 +159,33 @@ elems = M.elems . unpack
148159keys :: MonoidalHashMap k a -> [k]
149160keys = M.keys . unpack
150161{-# INLINE keys #-}
162+
163+-- | /O(log n)/. Modify a value on some key with a function, if value
164+-- under key doesn't exist -- use mempty.
165+modify :: (Monoid a, Hashable k, Eq k)
166+ => (a -> a)
167+ -> k -> MonoidalHashMap k a
168+ -> MonoidalHashMap k a
169+modify f k = pack
170+ . M.insertWith (\_ old -> f old) k (f mempty)
171+ . unpack
172+{-# INLINE modify #-}
173+
174+-- | /O(log n)/. Modify a value on some key with a function, providing
175+-- a default value if that key doesn't exist.
176+modifyDef :: (Monoid a, Hashable k, Eq k)
177+ => a -> (a -> a)
178+ -> k -> MonoidalHashMap k a
179+ -> MonoidalHashMap k a
180+modifyDef d f k = pack
181+ . M.insertWith (\_ old -> f old) k d
182+ . unpack
183+{-# INLINE modifyDef #-}
184+
185+-- | /O(n)/. Map a function to each key of a map
186+mapKeys :: (Monoid a, Hashable k, Eq k, Hashable k', Eq k')
187+ => (k -> k') -> MonoidalHashMap k a
188+ -> MonoidalHashMap k' a
189+mapKeys f = fromList
190+ . map (\(k, v) -> (f k, v))
191+ . toList