我是Haskell的初学者,
我有一个功能
func :: Num a => [a] -> [a]
func [] = []
func (x:xs) = x + func xs
每次递归我想将值附加到输出的列表中。此函数将对列表中的连续索引求和,以便输入[1, 2, 3, 4]
生成[1, 3, 6, 10]
。
如何将每次生成的值附加到列表中?
答案 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是整数加法的标识,所以我们应该使用它。
最后,我们通过您的列表来获得结果。
尝试弄清楚如何将功能编写为折叠,然后作为扫描,您将发现答案。