type Natural = Integer

Stream :: Natural -> Bool

search

Stream

search :: (Stream -> Bool) -> Bool

search



11110011100011001111110100000000000000000...



search

search

search

p

p

p

search

p

p

p



d p (00000....) = 1



d p (10000....) = 2



d p (01000....) = 3



d p (11000....) = 4



and so on.



p

p

p

p

search

There has been a bit of talk recently about how it is possible to exhaustively search certain infinite spaces in a finite time. Unfortunately the explanations seem to be couched in topological language making them a little inaccessible. So I thought it'd be good to attempt a rigorous, but elementary, proof so that is possible to see exactly where the 'magic' happens.Consider the type of infinite streams of booleans:Can we write a function, that takes as argument a boolean predicate on, and tells us whether or not there is a stream that satisfies it?This sounds like an impossible task. There are uncountable many infinite streams of booleans, so how can we hope to search them all? There's one important thing in our favour: we're restricting ourselves to predicates that are computable and total. In other words, whatever stream we pass to the predicate, they have to return a boolean in a finite time.First, let's deal with an objection that makeseem impossible to implement. Given a 4-tuple of integers, we can encode these integers in a stream. For example, the integers (written in binary) (11,10,1,111) could be encoded aswhere we code the binary digit b as 1b, we separate the integers using 00 and terminate the sequence using 01. We could then write a predicate that checks to see if the 4-tuple gives a solution to x+y=zwith x,y,z>0 and n>=2. Plugging that intowe apparently have a way to decide the Fermat-Wiles theorem without doing any difficult number theory. Surely, therefore,can't exist? But the predicate we've just described isn't total. Suppose we feed it the string 111111... as input. It's going to think that these represent an x with leading digits 111... and it's going to sit there collecting digits forever. It's never going to terminate. So the requirement that the predicate be total is such a strong condition that we can't actually implement the Fermat predicate, even though it uses nothing more than simple arithmetic. So maybeis beginning to look a little more plausible.Here's the key thing: any predicate on boolean streams must terminate after a finite time, meaning it only reads a finite number of booleans. So given any predicate p, there is a (mathematical) function don the boolean streams with the property that d(s) is the index of the last bit p looks at when given s as input. d(s) is obviously always finite.Now at this point you might immediately jump to the opposite conclusion that of courseis possible because you only need to check a finite number of bits. But even though d(s) is always finite, it might be unbounded as s varies over the infinite set of streams. So the finiteness of don its own is not enough to bound our search. For example, consider predicates on 4-tuples of integers again. Each of these predicates reads only a finite number of bits, and yet we don't expect a general purpose terminating search algorithm can tell us whether or not Fermat's equation has a solution. So to prove termination for the boolean stream case we need to exploit some more structure.Here's a first hint at what that structure might be. Suppose we try to make dunbounded by arranging thatYou might notice that we immediately have a contradiction. If d(00000...)=1 then the predicate must stop reading bits after it has read an initial 0. So actually, the sequence d(01000...) is also 1. Lots of streams share prefixes in this way, so the question is, does the infinitude of the set of boolean streams win out, or does the amount of sharing of prefixes eventually tame the infinity?Consider the following infinite binary tree:Each boolean stream corresponds to a single downward path through this tree. Fix a predicate p. Suppose, then, that this predicate, when fed the stream 011..., requires only 3 bits to be read, ie. d(011...) = 3. Then we can cut off everything below that point on the tree because no predicate need read that far. We've removed every infinite path passing through 011:Every stream s has a finite cutoff after d(s) steps. And after we've hacked away all of the bits that our predicate never looks at what we're left with is a finitely branching tree with no infinite paths. Now comes the magic: we invoke König's Lemma which says "every tree that contains infinitely many vertices, each having finite degree, has at least one infinite simple path.". Conversely, if there are no infinite paths, the tree must be finite. In other words, for any predicate p we only need to search a finite tree.The rest is just details, such as the precise method by which we determine when we've finished searching. In the case of Martín Escardó's paper the details are some of the most ingenious coding I've ever seen.Update: I fixed the type ofabove. Thanks to Cale for pointing this out. Unfortunately I deleted his comment by accident so I'm crediting him here.