使用 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
将导致计算 n
和 n : countup (n + 1)
。评估后者什么都不做(它已经被评估),并且评估前者执行任何加法,以便 + 1
s 永远不会建立起来。根据这个定义,take k (countup n)
需要 O(1)
space(或者,实际上是 O(log(n + k))
)。
我们也可以把改进后的函数写成
countup !n = n : countup (n + 1)
我不是很明白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
将导致计算 n
和 n : countup (n + 1)
。评估后者什么都不做(它已经被评估),并且评估前者执行任何加法,以便 + 1
s 永远不会建立起来。根据这个定义,take k (countup n)
需要 O(1)
space(或者,实际上是 O(log(n + k))
)。
我们也可以把改进后的函数写成
countup !n = n : countup (n + 1)