We have already met infinite lists in Chapter 4 and even given an induction principle for reasoning about them in Chapter 6. But we haven't really appreciated what can be done with them. In this chapter we want to explain in more detail exactly what an infinite list is, and how they can be represented by cyclic structures. We also describe another useful method for reasoning about infinite lists, and discuss a number of intriguing examples in which infinite and cyclic lists can be used to good effect.
Review
Recall that [m‥] denotes the infinite list of all integers from m onwards:
ghci> [1‥]
[1,2,3,4,5,6,7,{Interrupted}
ghci> zip [1‥] “hallo”
[(1,'h'),(2,'a'),(3,'l'),(4,'l'),(5,'o')]
It would take forever to print [1‥], so we interrupt the first computation. The second example illustrates a simple but typical use of infinite lists in finite computations.
In Haskell, the arithmetic expression [m‥] is translated into enumFrom m, where enumFrom is a method in the Enum class, and defined by
enumFrom :: Integer → [Integer]
enumFrom m = m:enumFrom (m+1)
Thus [m‥] is defined as an instance of a recursively defined function. The computation makes progress because (:) is non-strict in its second argument.
It is important to bear in mind that infinite lists in computing do not have the same properties as infinite sets do in mathematics.