【问题标题】:Processing a list 1..n elements at a time without explicit recursion一次处理列表 1..n 个元素,无需显式递归
【发布时间】:2011-05-28 08:14:08
【问题描述】:

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

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

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

【问题讨论】:

  • 那将是一个不错的组合器。我通过hoogle找不到它。我的搜索词是([a] -> (b,[a])) -> [a] -> [b]

标签: haskell recursion


【解决方案1】:

你需要的函数类似于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)

【讨论】:

  • 我明白你想说什么,consume 的这种类型以Maybe 结尾,或者你重新定义consume 并使用wrap,但它得到了乱码(不输入检查)。您要么需要join . wrap consume,要么需要更明确的consume :: [a] -> (b,[a])。实际上,您会得到一个 Maybe (Maybe (b,[a]) 被传递给 unfoldr
  • @TomMD 修正了 consume 的歧义。我希望consume 是最后一个示例中的原始consume
【解决方案2】:

您可以使用unfoldrconsume 周围的一些包装器,但我希望那里有一个更适合您所拥有的模式的函数。我建议在Data.List 中添加一个。我也经常用。

【讨论】:

  • 完全同意。对于Data.List,这将是一个非常有用的功能。
猜你喜欢
  • 2013-12-05
  • 1970-01-01
  • 1970-01-01
  • 2019-04-01
  • 1970-01-01
  • 2021-07-12
  • 1970-01-01
  • 2022-01-25
  • 1970-01-01
相关资源
最近更新 更多