使用 seq 实现无限列表以提高 Haskell 中的时间复杂度

Implementing an infinite list with seq to improve time complexity in Haskell

我不是很明白seq到底是怎么工作的以及如何使用seq实现一个函数。 因此,作为练习,如果我想实现一个生成以数字 a.

开头的列表的函数

例如,我正在使用以下函数

countup n = n : countup (n+1)

并尝试获取 [1, 2, 3, 4 ...](从 1 开始,只需递增 1 并添加到列表中)作为无限惰性列表。 我应该怎么做?

更新:

我试图使(取 k(计数 0))使用 O(1) space。 这里take函数如下:

take k (x:xl) = 
    if k==0
    then x
    else take (k-1) xl
countup n = n : countup (n+1)

列表中的每个元素都创建为一个 thunk previousElement + 1。因此,如果您 take 第 1000000 个或任何元素,那将是一个非常大的 thunk (...(n + 1)... + 1),其中包含约 1000000 个暂停。尽管 :-cells 可以在创建后立即进行 GC(因此遍历列表脊椎本身需要 O(1) space),元素本身会复制列表的结构所以 take k (countup n) 仍然需要 O(k) space.

如果评估 : 单元格也能评估元素,我们会很高兴。我们可以用

countup n = seq n $ n : countup (n + 1)

现在,在计算 seq n $ n : countup (n + 1) 时,seq 将导致计算 nn : countup (n + 1)。评估后者什么都不做(它已经被评估),并且评估前者执行任何加法,以便 + 1s 永远不会建立起来。根据这个定义,take k (countup n) 需要 O(1) space(或者,实际上是 O(log(n + k)))。

我们也可以把改进后的函数写成

countup !n = n : countup (n + 1)