lstsAdder :: [[Integer]] -> [Integer]
lstsAdder [] = []
lstsAdder (x:xs) = zipWith (+) x (lstsAdder xs)
正如标题所说,我希望它以递归方式添加:[[a,b,c],[d,e,f]]
,如下所示:[a+d,b+e,c+f]
,以及任何有限长度的列表列表。但我的所有实现返回都是[]
。为什么会这样,我该如何解决?
答案 0 :(得分:5)
您的递归基本案例会返回[]
和length (zipWith f a b) = min (length a) (length b)
。这意味着您的结果始终为长度0. min
的标识元素为+无穷大,(+)
的标识元素为0
,因此一个可能的基本情况为{{1} }。
您还可以查看数据的前置条件是否允许您执行类似
的操作repeat 0
它具有不同的边缘情况行为(import Data.List (transpose)
lstsAdder = map sum . transpose
给出QuickCheck
作为一个示例输入)但是在实践中可能不会出现这些边缘情况。
答案 1 :(得分:3)
你的基本情况太基础了......函数将以递归方式消耗所有行。当它一直向下递归堆栈时,它留下了空列表,即没有行的列表。这将返回一个空结果。
然后,返回递归堆栈,应该使用+
将每个图层压缩到它上面。好吧,但是用空列表压缩任何列表都会产生一个空列表!
有三种方法可以解决此问题:
为单行矩阵添加额外的基本案例。如果只有一行,结果应该只是那行,对吗?
lstsAdder [] = []
lstsAdder [r] = r
lstsAdder (x:xs) = zipWith (+) x $ lstsAdder xs
在压缩步骤中用零填充缺少的元素。
lstsAdder [] = []
lstsAdder (x:xs) = x ^+^ lstsAdder xs
infixrl 6 ^+^
(^+^) :: [a] -> [a] -> [a]
xs^+^[] = xs
[]^+^ys = ys
(x:xs)^+^(y:ys) = (x+y) : (xs^+^ys)
为基本案例提供无限的零列表:
lstsAdder [] = repeat 0
lstsAdder (x:xs) = zipWith (+) x $ lstsAdder xs
答案 2 :(得分:1)
我相信您也可以使用以下单个foldr1
操作;
listsAdd :: (Foldable t, Num c) => t [c] -> [c]
listsAdd = foldr1 (zipWith (+))
*Main> listsAdd [[1,2,3],[4,5,6]]
[5,7,9]