我想在Haskell中使用递归。我定义:
pf:: Int -> Int
pf 1 = 1
pf n = pf 1 + sum[pf 1..pf n-1]
但总和不正确!总结函数列表的正确方法是什么?
答案 0 :(得分:6)
[pf 1..pf (n-1)]
与[pf 1, pf 2, pf 3, ..., pf (n-1)]
不同。
> let f x = 2^x
> [f 1 .. f 4]
[2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
> [f 1, f 2, f 3, f 4]
[2,4,8,16]
您可能需要map
:
pf n = pf 1 + sum (map pf [1..n-1])
而且,正如一句话pf x = 2^(x-1)
。
答案 1 :(得分:0)
从接受的答案开始,我们可以进行以下改进
pf n = pf 1 + sum (map pf [1..n-1])
我们将pf 1与一个总和相加,然后它只是一个总和
通常的总和可以使用折叠表达如下
sum = fold (+) 0
这里0可以作为总和的种子,以说服你在ghci中输入以下两个表达式
foldl (+) 10 [1..10] -- return 65
10 + sum [1..10] -- return 65 too
在我们的示例中,种子等于 pf 1 ,这导致我们
pf n = foldl (+) (pf 1) (map pf [1..n-1])
我们可以重写一个术语,这次我将重点关注列表范围[1..n-1]
enumFromTo 1 (n-1) = [1..n-1]
或者n-1可以重写(再次)作为pred n,然后我们有
enumFromTo 1 (pred n) = [1..n-1]
代入主表达式,我们得到
pf n = foldl (+) (pf 1) (map pf (enumFromTo 1 (pred n)))
现在我们可以用点自由样式表达主表达式
pf = foldl (+) (pf 1) . map pf . enumFromTo 1 . pred
我们可以做更多的考虑,而不是地图可以表达折叠,但我们肯定会失去可读性,只需注意
map f = foldl (\x xs -> f x : xs) []