Haskell:如何汇总函数列表?

时间:2013-02-03 19:20:44

标签: haskell

我想在Haskell中使用递归。我定义:

pf:: Int -> Int
pf 1 = 1
pf n = pf 1 + sum[pf 1..pf n-1]

但总和不正确!总结函数列表的正确方法是什么?

2 个答案:

答案 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) []