patternModerate
Update Map in Haskell
Viewed 0 times
mapupdatehaskell
Problem
I wrote a function that inserts or updates a
Tests
Please critique.
Map key value depending on whether the key is already in the map. If it is, then the value gets added to the already existing map's value.import Data.Map as Map
updateMap :: (Ord k, Num v) => k -> v -> Map k v -> Map k v
updateMap k v map = if member k map then Map.adjust (+ v) k map
else Map.insert k v mapTests
*Main> updateMap 1 1 $ Map.singleton 1 100
fromList [(1,101)]
*Main> updateMap 2 1 $ Map.singleton 1 100
fromList [(1,100),(2,1)]
*Main> updateMap 1 33 $ Map.singleton 1 100
fromList [(1,133)]Please critique.
Solution
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 vRealize 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 aValidate 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.
Code Snippets
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)]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λ> :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λ> 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)]Context
StackExchange Code Review Q#57843, answer score: 13
Revisions (0)
No revisions yet.