我是一个Haskell初学者,哈斯克尔递归并添加到列表
我有一个函数
func :: Num a => [a] -> [a]
func [] = []
func (x:xs) = x + func xs
每个递归我想要的价值附加到了我的输出列表。该函数将对列表中的连续索引进行求和,以使输入[1, 2, 3, 4]
产生[1, 3, 6, 10]
。
如何将每次生成的值附加到我的列表中?
我是一个Haskell初学者,哈斯克尔递归并添加到列表
我有一个函数
func :: Num a => [a] -> [a]
func [] = []
func (x:xs) = x + func xs
每个递归我想要的价值附加到了我的输出列表。该函数将对列表中的连续索引进行求和,以使输入[1, 2, 3, 4]
产生[1, 3, 6, 10]
。
如何将每次生成的值附加到我的列表中?
这里你的问题不是如何追加,而是如何计算第一个值。每个项目都需要用它自身的总和代替它之前的所有项目。
下面是做到这一点的一种方法:
Prelude> func (x:xs) = x:map (+ x) (func xs); func [] = []
Prelude> func [1, 2, 3, 4]
[1,3,6,10]
这是如何工作的?我们给出了一个以元素x
开头的列表,其余元素xs
。我们希望递归地将算法应用于xs
后,将xs
中的每个项目递增x
。
这是x:map (+ x) (func xs)
所做的。它读作为“在func xs
中通过x
的增量映射每个元素的结果”前面加上x
“。
例如,对于[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]
。
你能解释这是如何工作的吗? –
@JamesHamish当然,我会扩大答案。我应该提到,更常用的方法是'scanl',如其他答案所示,所以您可能想要使用/接受该方法。 –
我认为在这种特殊情况下,你可以使用scanl1
像:
scanl1 (+) [1,2,3,4] -- [1,3,6,10]
当遍历列表,我们经常使用褶皱,这正是该列表缩减为特定值的方式。
还有另一种类型的操作,这是收集沿途所有结果倍,这就是所谓的一个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是整数加法的标识,所以我们应该使用它。
最后,我们通过您的列表来获得结果。
试图弄清楚如何写作为折叠功能,然后作为扫描,你会发现答案。
你忘了问一个问题。但是,是的,你需要一个停止条件(基本情况) –
我现在编辑 –
'0'不是一个列表。 – melpomene