矩阵到单行的递归和列(带zipWith(+))

时间:2017-09-06 13:41:41

标签: haskell recursion matrix zipwith

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

正如标题所说,我希望它以递归方式添加:[[a,b,c],[d,e,f]],如下所示:[a+d,b+e,c+f],以及任何有限长度的列表列表。但我的所有实现返回都是[]。为什么会这样,我该如何解决?

3 个答案:

答案 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]