I'm trying to reduce a list of tuples, where the values of a duplicate key are added together like this:
[(the, 1), (the, 1)] => [(the, 2)]
I tried this:
reduce :: [(String, Integer)] -> [(String, Integer)]
reduce [] = []
reduce [(k, v) : xs] = (+) [(k, v)] : reduce xs
I'm getting this error:
Couldn't match expected type `(String, Integer)'
with actual type `[(String, Integer)] -> [(String, Integer)]'
What am I doing wrong?
Edit
This is the full program
toTuple :: [String] -> [(String, Integer)]
toTuple [] = []
toTuple (k:xs) = (k, 1) : toTuple xs
reduce :: [(String, Integer)] -> [(String, Integer)]
reduce [] = []
reduce [(k, v) : xs] = (+) [(k, v)] : reduce xs
main_ = do list <- getWords "test.txt"
print $ reduce $ toTuple list
-- Loads words from a text file into a list.
getWords :: FilePath -> IO [String]
getWords path = do contents <- readFile path
return ([Prelude.map toLower x | x <- words contents])
You are doing the pattern matching wrong. The pattern match should be like this:
((k,v):xs)
(k,v) represents the head of the list and xs represents the tail of the list. Similarly this is problematic:
(+) [(k, v)] : reduce xs
The type of + is this:
λ> :t (+)
(+) :: Num a => a -> a -> a
You cannot simply do (+) [(k, v)] : reduce xs which doesn't appear anywhere reasonable. You have to check the contents of the String and then add second part of the tuple.
Let me point out that your function reduce is extremely similar to function fromListWith from Data.Map:
> :m Data.Map
> let reduce = toList . fromListWith (+)
> :t reduce
reduce :: (Ord k, Num a) => [(k, a)] -> [(k, a)]
> reduce [('a', 3), ('a', 1), ('b', 2), ('a', 10), ('b', 2), ('c', 1)]
[('a',14),('b',4),('c',1)]
> reduce [(c,1) | c <- "the quick brown fox jumps over the lazy dog"]
[(' ',8),('a',1),('b',1),('c',1),('d',1),('e',3),('f',1),('g',1),('h',2),('i',1),('j',1),('k',1),('l',1),('m',1),('n',1),('o',4),('p',1),('q',1),('r',2),('s',1),('t',2),('u',2),('v',1),('w',1),('x',1),('y',1),('z',1)]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With