0

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

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

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

4

2 回答 2

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)

于 2013-02-03T19:26:47.757 回答
0

从接受的答案开始,我们可以做以下细化

pf n = pf 1 + sum (map pf [1..n-1])

我们将 pf 1 与一个总和相加,然后它只是一个总和
通常的总和可以使用 fold 表示如下

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 可以用折叠来表达,但肯定我们会失去可读性,请注意

map f = foldl (\x xs -> f x : xs) [] 
于 2013-02-17T01:51:36.490 回答