我有一系列数字:0,1,3,6,10,15 ...... 基本上,你添加1,然后你添加2,然后添加3,等等。
我必须创建一个函数,在列表中返回给定数字n的这一系列数字。我想用foldl。
所以,系列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)来完成此任务。
然而,它返回的列表比我想要的要大得多。
EG。系列3 =&gt; [0,1,2,3,4,5,6]什么时候应该真的返回[0,1,3,6]
为什么会这样?
答案 0 :(得分:7)
scanl
更适合您正在做的事情。
其类型为scanl :: (a -> b -> a) -> a -> [b] -> [a]
- 其类型签名与foldl
相同,但它返回增量值列表,而不仅仅是最终结果。
我会把剩下的作为锻炼给你,因为这看起来像是家庭作业。祝你好运!
答案 1 :(得分: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
或类似的概念来构建列表。
答案 2 :(得分:1)
scanl是最好的,但是如果你必须使用折叠试试这个
testso :: Integral a => a -> [a]
testso n = reverse $ foldl (\acc x -> head acc + x:acc ) [0] [1,2..n]
输出为testso 10 [0,1,3,6,10,15,21,28,36,45,55]。
答案 3 :(得分:0)
当你写[a,b..c]时,a是第一个元素,c是最后一个元素,b是步骤,它是列表中每个元素之间的间隔,如果省略它,它将是默认为1。
让我们看一下你的代码吧:
[x | x <- [(eachElem 0), (eachElem 1)..(eachElem n)]]
因此你的结果:[0,1 ..(eachElem n)]产生[0,1,2,3 ...并且显然不是你所期望的。
正如amindfv所建议的那样,你应该看看scanl。
答案 4 :(得分:0)
您对series
的定义是错误的。
[(eachElem 0), (eachElem 1)..(eachElem n)]
变为[0, 1, eachElem n]
,实际上每个数字都会达到eachElem n
。
你真的想这样做:
series n = [eachElem x | x <- [0..n]]
答案 5 :(得分: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
答案 6 :(得分:0)
你可以作弊: - )
series x = foldl (\xs n -> (n*(n+1) `div` 2):xs) [] [x,(x-1)..0]