问题描述
我不太明白 seq 究竟是如何工作的,以及如何使用 seq 实现一个功能。 所以作为一个练习,如果我想实现一个函数来生成一个以数字 a 开头的列表。
例如,我正在使用以下功能
countup n = n : countup (n+1)
并尝试将 [1,2,3,4 ...] (从 1 开始,只需增加 1 并添加到列表中)作为一个无限的惰性列表。 我该怎么做?
更新:
我正在尝试使 (take k (countup 0)) 使用 O(1) 空间。 这里,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 个暂停。尽管 :
单元可以在创建后立即被 GC 处理(因此遍历列表脊本身需要 O(1)
空间),但元素本身复制了列表的结构,因此 {{ 1}} 仍然占用 take k (countup n)
空间。
如果评估 O(k)
单元格也会评估元素,我们会很高兴。我们可以用
:
现在,在评估 countup n = seq n $ n : countup (n + 1)
时,seq n $ n : countup (n + 1)
将导致 seq
和 n
被评估。评估后者什么都不做(它已经被评估了),评估前者会执行任何 thunked 加法,以便 n : countup (n + 1)
永远不会建立。根据这个定义,+ 1
占用 take k (countup n)
空间(或者,实际上是 O(1)
)。
我们也可以将改进后的函数写成
O(log(n + k))