【问题标题】:Haskell sublist with foldr带有 foldr 的 Haskell 子列表
【发布时间】:2017-05-24 22:54:43
【问题描述】:

我正在尝试在 haskell 中创建一个函数,但我的目标是通过在列表上使用 foldr 来实现,这是一个示例:

sublistas [5,1,2] 
 [[],[2],[1],[1,2],[5],[5,2],[5,1],[5,1,2]]

效率不是问题。到目前为止我尝试的方法给了我错误:

无法构造无限类型.....

sublistas = foldr (\x rs -> [x] ++ map (x:) rs) [[]]

我尝试了很长时间,也许有人可以在这里给我一些想法?

【问题讨论】:

  • 您是否故意遗漏了[5,2],因为您只想要连续的子列表?
  • 不不@Alec,我忘记了,谢谢,我更新了q
  • 没有foldr 的等价物是sublistas = filterM (const [True, False])
  • sublists = foldr (\x l -> l ++ map (x:) l) [[]]
  • 对于 funzies,连续的子列表将是 sublistas xs = tails xs >>= tail . inits

标签: haskell combinations fold


【解决方案1】:

你可以使用:

foldr (\x rs -&gt; <b>rs</b> ++ map (x:) rs) [[]]

例如:

Prelude> foldr (\x rs -> rs ++ map (x:) rs) [[]] [5,1,2]
[[],[2],[1],[1,2],[5],[5,2],[5,1],[5,1,2]]

建议的foldr 的工作方式如下:我们从[[]] 开始。现在对于元素x,我们生成所有已生成列表的连接(在第一步中[],这些列表以元素为前缀,所以[2])。

所以在第一步之后,我们获得了[[],[2]]。接下来我们再次弃牌,现在我们生成[[],[2],[1],[1,2]]。最后我们还使用5,产生[[],[2],[1],[1,2],[5],[5,2],[5,1],[5,1,2]]。

上面的解释必须以一种懒惰的方式来看待:rs 不需要计算(首先),除非有必要。


您的 lambda 表达式 \x rs -&gt; [x] ++ map (x:) rs 不正确有两个原因:

  • [x] 是一个包含您提供的列表的 item 的列表,而不是您提供的项目列表的列表,因此是类型错误;和
  • 无论如何,您都不应该在结果中添加[x]:您将传递所有已生成的元素,以及您在前面添加x 的所有元素。

【讨论】:

  • 效果很好,你介意给我解释一下,你为什么放 rs ++ map ... 为什么?它是如何工作的?
  • foldr 只是遍历列表,累积部分结果。以您的示例-sublistas [5,1,2] = f 5 (f 1 ( f 2 ([[]])))。考虑最后一步 - f 5 [[],[2],[1],[1,2]] 在最终结果中,我们希望看到两种类型的子列表 - 具有 5 的子列表是 map (x:) rs,而没有的子列表只是 rs。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-21
  • 1970-01-01
  • 1970-01-01
  • 2015-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多