Haskell中列表的部分折叠

时间:2014-03-24 07:41:18

标签: haskell fold

如何仅有限次数应用fold个函数,而不是折叠整个列表?例如,这个不完整的折叠只会总结前3个数字,其余部分保持不变:

foldlN 3 (+) [1..5] -- [6,4,5]

2 个答案:

答案 0 :(得分:2)

在列表的一部分上折叠似乎很简单,然后将其合并到列表的其余部分:

foldlN :: Int -> (a -> a -> a) -> [a] -> [a]
foldlN n f xs = (foldl1 f $ take n xs) : drop n xs

REPL中的结果:

*Main> foldlN 3 (+) [1..5]
[6,4,5]

如果您担心从同一个列表中删除然后删除是双重作业,则可以使用splitAt重写:

foldlN n f xs = (foldl1 f $ fst t) : snd t
  where t = splitAt n xs

请注意函数的类型,您不能在foldl上进行折叠,因为在Haskell中不能有列表[[1,2,3],4,5,6]

答案 1 :(得分:1)

首先,折叠包含(+)的列表并不会生成列表,它会生成一个答案。也许您想要scanlscanr

scanl (+) 0 [1..5] -- [0, 0+1, 0+1+2, 0+1+2+3, ...]

因此,如果您只想添加前3个数字,那么这将是此列表的第4个元素;

(scanl (+) 0 [1..5]) !! 3

或者,您可以将列表缩减为3个元素:

foldl (+) 0 (take 3 [1..5])