Precise Reasoning About Non-strict Functional Programs; How to Chase Bottoms, and How to Ignore Them
This thesis consists of two parts. Both concern reasoning about non-strict functional programming languages with partial and infinite values and lifted types, including lifted function spaces.
The first part is a case study in program verification: We have written a simple parser and a corresponding pretty-printer in Haskell. A natural aim is to prove that the programs are, in some sense, each other's inverses. The presence of partial and infinite values makes this exercise interesting. We have tackled the problem in different ways, and report on the merits of those approaches. More specifically, first a method for testing properties of programs in the presence of partial and infinite values is described. By testing before proving we avoid wasting time trying to prove statements that are not valid. Then it is proved that the programs we have written are in fact (more or less) inverses using first fixpoint induction and then the approximation lemma.
Using the proof methods described in the first part can be cumbersome. As an alternative, the second part justifies reasoning about non-total (partial) functional languages using methods seemingly only valid for total ones. Two languages are defined, one total and one partial, with identical syntax. A partial equivalence relation is then defined, the domain of which is the total subset of the partial language. It is proved that if two closed terms have the same semantics in the total language, then they have related semantics in the partial language.