我开始尝试使用Haskell并遇到sum
函数的以下实现:
sum [] = 0
sum (x:xs) = x + sum xs
然后有一个解释显示该函数在一个真实的例子中的行为:
sum [1,2,3]
1 + (sum [2,3])
1 + (2 + sum [3])
1 + (2 + (3 + sum []))
1 + (2 + (3 + 0))
= 6
我不明白,为什么每次调用sum [x]
时,列表会减少1个元素?
我唯一的假设是,当执行构造(x:xs)
时,列表的元素x
不仅被检索,而且被删除(类似于堆栈pop()
方法。),但我不确定。
答案 0 :(得分:5)
在符号x:xs
中,x是列表的头部,即1项,xs是列表的尾部,是0个或更多项的列表。
由于递归调用是在xs上,因此每个递归级别的问题大小集都会减少1。
答案 1 :(得分:5)
没有“从列表中删除元素”这样的事情。列表是不可变的,就像任何其他对象一样。现在,关于实施,在:
sum (x:xs) = x + sum xs
您将列表匹配到其头部x
和列表的其余部分(没有头部)xs
。具体来说,在sum [1, 2, 3]
中,您会得到:
sum (1:[2, 3]) = 1 + sum [2, 3]
如果您还记得,(:)
用于将元素附加到列表中。所以:1:[2, 3]
实际上是[1, 2, 3]
,也可以写成:1:2:3:[]
。
您应该记住的唯一事情是(x:xs)
上的模式匹配,意味着:将列表的头部放在x
中,将列表的其余部分放在xs
中。
答案 2 :(得分:2)
基本上,你再次调用该函数,其余的列表与第一个元素相加。