在Haskell中是否可以编写一个函数来汇总整数列表中的所有项目,如果列表中间的总和小于0,那么重新启动加起来为0.我的意思是这样的:
[2,5,-6,-2,8,4]
2 + 5 = 7
7 - 6 = 1
1 - 2 = -1 restart here because we are under 0
0 + 8 = 8
8 + 4 = 12
function return 12
当然我知道我可以使用以下代码添加列表中的所有项目:
sum :: [Int] -> Int
sum [x] = x
sum (x:l) = x + sum l
但是我不知道如果一个总和小于0我怎么能重新启动这个函数。对于那个或那个在功能编码语言中不可能的想法,因为我们没有真正的变量或其他什么?
答案 0 :(得分:3)
让我使用scanl
来显示正在发生的事情,然后使用foldl
来获取实际结果。
首先让我们尝试添加列表的所有元素:
Prelude> scanl (+) 0 [2,5,-6,-2,8,4]
[0,2,7,1,-1,7,11]
这相当于:
Prelude> scanl (\a b -> a+b) 0 [2,5,-6,-2,8,4]
[0,2,7,1,-1,7,11]
为了避免负面的中间数,你可以改变它:
Prelude> scanl (\a b -> max 0 (a+b)) 0 [2,5,-6,-2,8,4]
[0,2,7,1,0,8,12]
要仅获取实际结果,请将scanl
替换为foldl
:
Prelude> foldl (\a b -> max 0 (a+b)) 0 [2,5,-6,-2,8,4]
12
答案 1 :(得分:2)
很有可能,你使用累加器变量。
sumPos xs = go 0 xs where
go acc [] = acc
go acc (x:xs) = go (max (acc + x) 0) xs
这可以通过内置的递归函数来解决,例如foldl'
非常好。
sumPos = foldl' step 0 where
step x acc = max 0 (x + acc)
如果您像某些人一样定义foldl' (max 0 .: (+)) 0
,则甚至可以(.:) = (.).(.)
。