我发现自己经常使用一种模式,我用一个函数转换一个列表,该函数从列表中消耗1..n个元素并从中产生一些结果。 E.g。
process :: [a] -> [b]
process [] = []
process xs = first : rest
where (first, xs') = consume xs
rest = process xs'
consume
函数从列表中消耗可变数量的项并返回结果和剩余的列表项。我可以在这里使用一些标准的高阶函数而不是显式递归吗?
答案 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
然后,您可以将consume
与unfoldr
一起使用consume :: [a] -> (b,[a])
的原始定义,如下所示:
unfoldr (wrap consume)
答案 1 :(得分:3)
你可以使用unfoldr
和consume
之间的一些包装器,但是我希望那里有一个更高阶函数,以确保你拥有的模式。我建议在Data.List
添加一个。我也经常使用它。