0
lstsAdder :: [[Integer]] -> [Integer]
lstsAdder [] = []
lstsAdder (x:xs) = zipWith (+) x (lstsAdder xs)

As the title says, I want it to recursively add this: [[a,b,c],[d,e,f]] like this: [a+d,b+e,c+f], and this with lists of lists of any finite length. But all my implementation returns is []. Why is that, and how do I fix it?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
majorTom
  • 57
  • 6

3 Answers3

5

Your recursion base case returns [], and length (zipWith f a b) = min (length a) (length b). This means your result will always have length 0. The identity element for min is +infinity, and the identity element for (+) is 0, so one possible base case is repeat 0.

You could also see if pre-conditions on the data would allow you to do something like

import Data.List (transpose)
lstsAdder = map sum . transpose

It has different edge-case behaviour (QuickCheck gives [[0,0],[0]] as one example input) but maybe those edge cases won't occur for you in practice.

Claude
  • 1,014
  • 7
  • 13
3

Your base case is too basic... the function will recursively consume all rows. When it's all the way down the recursion stack, it's left with the empty list, i.e. the list with no rows. This returns an empty result.

But then, going back the recursion stack, each layer is supposed to be zipped onto it with +. Well, but zipping any list with an empty list results in an empty list!

There are three ways you can adress this issue:

  • Add an extra base case for one-row matrices. If there's only one row, the result should be just that row, right?

    lstsAdder [] = []
    lstsAdder [r] = r
    lstsAdder (x:xs) = zipWith (+) x $ lstsAdder xs
    
  • Fill missing elements with zeroes in the zipping step.

    lstsAdder [] = []
    lstsAdder (x:xs) = x ^+^ lstsAdder xs
    
    infixrl 6 ^+^
    (^+^) :: [a] -> [a] -> [a]
    xs^+^[] = xs
    []^+^ys = ys
    (x:xs)^+^(y:ys) = (x+y) : (xs^+^ys)
    
  • Give an infinite list of zeroes for the base case:

    lstsAdder [] = repeat 0
    lstsAdder (x:xs) = zipWith (+) x $ lstsAdder xs
    
leftaroundabout
  • 117,950
  • 5
  • 174
  • 319
  • in my case i don't need to fill missing zeroes since the function in witch i want to use this does it for me so thanks even tho i didn't really understand how your second point works (can do without it) – majorTom Sep 06 '17 at 14:32
1

I believe you may also do with a single foldr1 operation as follows;

listsAdd :: (Foldable t, Num c) => t [c] -> [c]
listsAdd =  foldr1 (zipWith (+))

*Main> listsAdd [[1,2,3],[4,5,6]]
[5,7,9]
Redu
  • 25,060
  • 6
  • 56
  • 76