【问题标题】:Haskell optimizing infinite list implementationHaskell优化无限列表实现
【发布时间】:2017-03-24 15:40:01
【问题描述】:

我的代码给出了想要的结果,但我想知道是否有更好的编码方法。这是给定的示例:

pair [ 1 , 2 , 3 , 4 , 5 , 6 , ... ]
[ [ 1 , 2 ] , [ 3 , 4 ] , [ 5 , 6 ] , ... ]

和给定的代码:

pair::[a] -> [[a]]
pair =

我的解决方案:

pair :: [a] -> [[a]]
pair (x:y:xs) = ((x:y:[]):[]) ++ pair xs

【问题讨论】:

  • 如果可以使用:,则不要连接列表:++O(n) 中工作(n 的大小与第一个list) 而 :O(1) 中工作。
  • @WillemVanOnsem 但是如果第一个列表的大小是 O(1) 就像在任何情况下,您都可以轻松地将 (++) 替换为 (:) 然后 (++)也是O(1)。因此,虽然(:) 可能是一个比(++) 快的常数因子,但它们是相同的。
  • 你没有提出问题。

标签: list haskell optimization infinite


【解决方案1】:

使用 cons 运算符 : 将比连接列表更高效:

pair :: [a] -> [[a]]
pair (x:y:xs) = [x, y] : pair xs

原因是 Haskell 中的列表是链表,其中每个项目都指向下一个项目,直到列表末尾。 Pushs 和 Pops 在列表头部完成时成本较低,因为您只是将头部指向现有列表的头部。

当你连接两个链表时,你实际上是在重建完整的第一个链表,以便它的最后一个元素可以指向第二个链表的第一个元素。

在您的示例中,性能提升很小,因为您的列表中只有两个元素,但作为一般规则,如果您正在处理列表头部的操作,它几乎总是会更高效使用缺点。

【讨论】:

  • 你测试过这个断言吗?在我的测试中,GHC 为两种实现发出完全相同的核心。
  • 我没有测试编译好的GHC。如果它能够在这种特定情况下进行优化,那就太酷了,我可以更新我的答案,但我认为一般规则是成立的,当: 足够时,我们不应该编码++,并且至少在理论上,性能更高。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-16
  • 1970-01-01
  • 2017-09-28
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多