2

我有一系列数字:0、1、3、6、10、15,...基本上,你加 1,然后加 2,然后加 3,等等。

我必须创建一个函数,将列表中的这一系列数字返回给定数字 n。我想使用折叠。

所以,系列 5 应该返回 [0, 1, 3, 6, 10, 15]

这是我到目前为止所拥有的:

eachElem n = foldl (+) 0 [0..n]

series n = [x | x <- [(eachElem 0), (eachElem 1)..(eachElem n)]]

基本上,我认为列表中的每个元素都是一个 foldl 操作,因此我制作了一个单独的辅助函数 (eachElem) 来完成此操作。

但是,它返回的列表比我想要的要大得多。

例如。系列 3 => [0,1,2,3,4,5,6] 它应该真正返回 [0,1,3,6]

任何想法为什么会这样?

4

7 回答 7

7

scanl更适合您正在做的事情。

它的类型是scanl :: (a -> b -> a) -> a -> [b] -> [a]——它的类型签名与foldl's 相同,但它返回一个增量值列表,而不仅仅是最终结果。

我会把剩下的留给你做练习,因为这看起来像是家庭作业。祝你好运!

于 2012-09-25T04:23:21.437 回答
2

如果你如此坚持使用foldl,你可以做类似的事情

series n  = reverse $ foldl f [0] [1..n]
    where f xs@(x:_) y = x+y:xs

在 ghci

> series 5
[0,1,3,6,10,15]

但问题foldl是你不能创建无限系列。

你可以有无限的系列像

series = 0:zipWith (+) series [1..]

然后你可以做类似的事情

> take (5+1) series
[0,1,3,6,10,15]

我没有尝试过,但您也可以使用unfoldr或类似的概念来构建您的列表。

于 2012-09-25T05:27:17.290 回答
1

scanl 是这里最好的,但如果你必须使用 fold 试试这个


testso :: Integral a => a -> [a]
testso n = reverse $ foldl (\acc x -> head acc + x:acc ) [0] [1,2..n] 

输出为 testo 10 [0,1,3,6,10,15,21,28,36,45,55]。

于 2012-09-25T08:13:00.847 回答
0

当你写[a,b..c]时,a是第一个元素,c是最后一个元素,b是步长,它是列表中每个元素之间的间隔,如果你省略它,它将默认为1 .

所以让我们看看你的代码,你这样做:

  [x | x <- [(eachElem 0), (eachElem 1)..(eachElem n)]] 
  • 在您的列表理解中, x 将首先取值 (eachElem 0) = 0
  • 那么下一个元素将是 (eachElem 0) + (eachElem 1) = 1
  • 那么第 i 个元素将是 (eachElem 0) + i*(eachElem 1 - eachElem 0) 只要值 <= (eachElem n)

因此,您的结果: [0,1..(eachElem n)] 产生 [0,1,2,3... 显然不是您所期望的。

正如 amindfv 所建议的,你应该看看 scanl。

于 2012-09-25T04:35:36.663 回答
0

你可以作弊:-)

series x = foldl (\xs n -> (n*(n+1) `div` 2):xs) [] [x,(x-1)..0]
于 2012-09-26T09:33:25.463 回答
0

你的定义series是错误的。

[(eachElem 0), (eachElem 1)..(eachElem n)]变成[0, 1, eachElem n]这实际上是每个数字eachElem n

你实际上想要这样做:

series n = [eachElem x | x <- [0..n]]
于 2012-09-25T05:27:37.803 回答
0

定义

series n = [ x | x <- [(eachElem 0)..(eachElem n)]]

是错的!

例如:

因为

eachElem 0 -> 0
eachElem 3 -> 6

系列 3 评估为

series 3 -> [(eachElem 0)..(eachElem 3)] -> [0..6] -> [0,1,2,3,4,5,6]

你需要这样的东西

series' n = [ eachElem x | x <- [0..n]]

测试:

> let series' n = [ eachElem x | x <- [0..n]]
> let series n = [ x | x <- [(eachElem 0)..(eachElem n)]]

> series' 3
> [0,1,3,6]

> series 3
> [0,1,2,3,4,5,6]

> eachElem 0
> 0

> eachElem 3
> 6
于 2012-09-25T13:28:43.213 回答