用折叠实现takeWhile

时间:2016-12-06 09:37:54

标签: haskell

如何使用fold?

在Haskell中实现takeWhile函数
takeWhile :: (a -> Bool) -> [a] -> [a]

我尝试了一种类似于实现此过滤器的策略

filter :: (a -> Bool) -> [a] -> [a]
filter f = foldr (\x acc -> if f x then x : acc else acc) []

但是当f x为假时我怎么能停止?

1 个答案:

答案 0 :(得分:8)

只需在acc分支中将[]更改为else

takeWhile f = foldr (\x acc -> if f x then x : acc else []) []

这个想法是你在使用输入列表中的元素时懒得构建结果列表,所以当你想终止结果列表时返回[]

takeWhile (< 3) [0..]
=
0 : takeWhile (< 3) [1..]
=
0 : 1 : takeWhile (< 3) [2..]
=
0 : 1 : 2 : takeWhile (< 3) [3..]
=
0 : 1 : 2 : []
=
[0, 1, 2]

这也说明了Haskell列表实际上是 streams 的值。右侧折叠是小型状态机,它们逐步移动输入流以生成输出流。