updateMapPF :: (Ord k, Num a) => k -> a -> Map k a -> Map k a
updateMapPF = Map.insertWith (+)
λ> updateMapPF 1 1 $ Map.singleton 1 100
fromList [(1,101)]
λ> updateMapPF 2 1 $ Map.singleton 1 100
fromList [(1,100),(2,1)]
λ> updateMapPF 1 33 $ Map.singleton 1 100
fromList [(1,133)]
Process:
Notice the use of Map.insert
Notice that you are mapping (+) over the possibility of having or not having a value
Notice that Data.Map has a function for applying functions to values, called Data.Map.insertWith. It's extremely common for collections to have a helper function for "insert data with a helper function / default value"
Notice the shared structure of the types of your function and insertWith
insertWith :: Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
updateMap :: (Ord k, Num v) => k -> v -> Map k v -> Map k v
Realize that applying (+) to insertWith will make the types identical
λ> :t insertWith
insertWith
:: Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
λ> :t insertWith (+)
insertWith (+) :: (Ord k, Num a) => k -> a -> Map k a -> Map k a
Validate assumptions with specific examples, more rigor is available with the use of QuickCheck.
λ> updateMapPF 1 1 $ Map.singleton 1 100
fromList [(1,101)]
λ> updateMapPF 2 1 $ Map.singleton 1 100
fromList [(1,100),(2,1)]
λ> updateMapPF 1 33 $ Map.singleton 1 100
fromList [(1,133)]
This is a practically golden opportunity to demonstrate how eta reduction can simplify code and kill off redundant logic.