在没有显式递归的情况下一次处理列表1..n个元素

时间:2011-05-28 08:14:09

标签: haskell recursion

我发现自己经常使用一种模式,我用一个函数转换一个列表,该函数从列表中消耗1..n个元素并从中产生一些结果。 E.g。

process :: [a] -> [b]
process [] = []
process xs = first : rest
    where (first, xs') = consume xs
          rest         = process xs'

consume函数从列表中消耗可变数量的项并返回结果和剩余的列表项。我可以在这里使用一些标准的高阶函数而不是显式递归吗?

2 个答案:

答案 0 :(得分:4)

您需要的功能类似于unfoldr。如果您将consume带入以下表单:

consume' :: [a] -> Maybe (b,[a])

如果列表为空,consume'会返回Nothing,否则会Just ...。这是一个小包装器,它捕获了这种模式:

wrap :: ([a] -> (b,[a])) -> [a] -> Maybe (b,[a])
wrap f [] = Nothing
wrap f xs = Just $ f xs

然后,您可以将consumeunfoldr一起使用consume :: [a] -> (b,[a])的原始定义,如下所示:

unfoldr (wrap consume)

答案 1 :(得分:3)

你可以使用unfoldrconsume之间的一些包装器,但是我希望那里有一个更高阶函数,以确保你拥有的模式。我建议在Data.List添加一个。我也经常使用它。