Reputation: 51
Essentially, I want to perform the following operation: [1, 2, 3, 4, 5, 6, 7] -> [3, 7, 11, 7]
In the above example, the element at the end of the list is left alone as there is nothing it can be added with since the list is odd in length.
I wanted to turn the list into a list of tuples such as [1, 2, 3, 4] -> [(1,2),(3,4)] then perform the addition on each tuple, but I could not figure out how to do that, and wasn't sure it would work with an odd length list.
Surely there is a way to add every two elements in a list.
Upvotes: 1
Views: 512
Reputation: 1310
One simple way to do this is via a basic recursive definition:
sumPairs :: Num a => [a] -> [a]
-- first, we deal with the base case
sumPairs [] = []
-- next we deal with the odd length list base case
sumPairs [x] = [x]
-- now we can recurse!
sumPairs (x:y:list) = (x+y) : sumPairs list
However, if you want to do this by combining existing functions, you can search hoogle for [a] -> [(a,a)]
(https://hoogle.haskell.org/?hoogle=%5Ba%5D+-%3E+%5B%28a%2Ca%29%5D&scope=set%3Astackage) to see if there are any relevant functions.
Unfortunately, it doesn't appear as if there are any. Some functions you could write, if you wanted something more compositional, are:
pairUp :: Num a => [a] -> [(a,a)]
pairUp [] = []
pairUp [x] = [(x, 0)]
pairUp (x:y:list) = (x,y) : pairUp list
sumPairs :: Num a => [a] -> [a]
sumPairs = map (uncurry (+)) . pairUp
Or, if you wanted to be even more generic
pairUp :: Monoid a => [a] -> [(a,a)]
pairUp [] = []
pairUp [x] = [(x, mempty)]
pairUp (x:y:list) = (x,y) : pairUp list
mergePairs :: Monoid a => [a] -> [a]
mergePairs = map (uncurry (<>)) . pairUp
and then
sumPairs :: Num a => [a] -> [a]
sumPairs = map getSum . mergePairs . map Sum
Or even
combinePairs :: (a -> a -> a) -> [a] -> [a]
combinePairs _ [] = []
combinePairs _ [x] = [x]
combinePairs _ (x:y:list) = f x y : combinePairs list
sumPairs :: Num a => [a] -> [a]
sumPairs = combinePairs (+)
Upvotes: 1
Reputation: 48672
For this problem, I think I'd fall back to explicit recursion:
sumPairs :: Num a => [a] -> [a]
sumPairs (x:y:ys) = x+y:sumPairs ys
sumPairs xs = xs
Nice and simple: if there's at least two elements, add them up then recurse to do the rest. Otherwise (meaning there's zero or one element), just return the same list you got.
Upvotes: 0