Haskell递归并添加到列表中

时间:2017-10-20 18:04:02

标签: list haskell

我是Haskell的初学者,

我有一个功能

func :: Num a => [a] -> [a]
func [] = []
func (x:xs) = x + func xs

每次递归我想将值附加到输出的列表中。此函数将对列表中的连续索引求和,以便输入[1, 2, 3, 4]生成[1, 3, 6, 10]

如何将每次生成的值附加到列表中?

3 个答案:

答案 0 :(得分:4)

我认为在这种特殊情况下,您可以使用scanl1之类的:

scanl1 (+) [1,2,3,4] -- [1,3,6,10]

答案 1 :(得分:4)

这里的问题不是如何追加,而是首先如何计算价值。每个项目都需要用自身的总和替换它前面的所有项目。

这是一种方法:

Prelude> func (x:xs) = x:map (+ x) (func xs); func [] = []
Prelude> func [1, 2, 3, 4]
[1,3,6,10]

这是如何工作的?我们给出了一个以元素x开头并具有剩余元素xs的列表。在递归地将算法应用于xs后,我们希望将x中的每个项目增加xs

这是x:map (+ x) (func xs)的作用。它将“x”映射为“func xs中每个元素通过x的增量映射的结果”。

E.g。对于[1, 2, 3, 4],我们希望将1添加到递归地将算法应用于[2, 3, 4]的结果的每个成员中,然后预先添加。对于[2, 3, 4],我们希望2为... [3, 4]。依此类推,直到最终[4]我们希望4添加并添加到将算法应用于[]的结果中。

这是我们的基本情况(func [] = [])开始的地方:定义算法以便它返回一个未更改的空列表。因此,func [4][4]func [3, 4][3, 7],并且您继续增加和提前,直到获得[1,3,6,10]

答案 2 :(得分:0)

当迭代列表时,我们经常使用folds,这是一种将列表减少到特定值的方法。

还有另一种类型的操作,即收集所有结果的折叠,称为scan(来自docs):

scanl                   = scanlGo
  where
    scanlGo           :: (b -> a -> b) -> b -> [a] -> [b]
    scanlGo f q ls    = q : (case ls of
                               []   -> []
                               x:xs -> scanlGo f (f q x) xs)

因此扫描采用三个参数:一个接受两个值并返回一个值的函数,一个起始值和一个值列表。

然后扫描将返回一个列表。

因此,你需要的是一个函数,它接受两个值并返回与第一个相同类型的东西(如果它们都相同则没关系)。二进制加法可以在这里工作:+

你还需要一个值来开始(b,这是我们函数的第二个参数),0是整数加法的标识,所以我们应该使用它。

最后,我们通过您的列表来获得结果。

尝试弄清楚如何将功能编写为折叠,然后作为扫描,您将发现答案。