在Haskell中,可以这样定义无限列表:
[1.. ]
如果找到了许多描述如何实现无限列表的文章,我知道这是如何工作的。但是,我想不出任何理由使用无限数据结构的概念。
有人可以给我举一个问题的例子,在Haskell中使用无限列表可以更容易(或仅可以解决)这个问题?
Haskell中列表的基本优点是它们是control结构,看起来像data结构。您可以编写对数据的[[streams进行增量操作的代码,但它对列表的简单操作却像对列表的简单操作那样。这与其他需要使用显式增量结构的语言形成了对比,例如迭代器(Python itertools
),协程(C#IEnumerable
)或范围(D)。例如,sort
函数可以这样编写:在开始产生结果之前,它对尽可能少的元素进行排序。在对entire
minimum xs = head (sort xs)
仅花费O(n)/ linear时间,因为 lookshead
仅检查列表的第一个构造函数,例如x : _
,将tail保留为未评估的重排,表示排序操作的其余部分。]这意味着性能是compositional:例如,如果您对数据流(例如sum . map (* 2) . filter (< 5)
)进行一长串操作,则[1, 2, 6]
,该过程基本上如下进行,所有步骤都是递增进行的:总计= 0
1 < 5
为真
1 * 2 == 2
0 + 2
= 2
2 < 5
为真2 * 2 == 4
2 + 4
= 6
6 < 5
为假6
total = 0;
for x in xs {
if (x < 5) {
total = total + x * 2;
}
}
这意味着
性能是组成的:由于懒惰,该代码在处理列表期间具有恒定的内存使用量。map
或filter
内部没有什么特别的可以实现的:它们可以完全独立。
[对于另一个示例,标准库中的and
计算列表的逻辑AND,例如and [a, b, c] == a && b && c
,并且可以简单地实现为折叠:and = foldr (&&) True
。一旦到达输入中的False
元素,它就会停止求值,这仅仅是因为&&
的正确参数很懒。懒惰给你构图![有关所有这些的出色论文,请阅读约翰·休斯着名的Why Functional Programming Matters,该书超越了我所能比的更好的惰性函数编程的优势(在Haskell的前身Miranda中)。