Automated Logic and Programming
Christoph Kreitz
Contents
1 Introduction
7
1.1
Outline . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8
1.2
References and further reading . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
2 Logic and computation
11
2.1
Formal Calculi
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.2
First Order Logic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.2.1
Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.2.2
Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.3
Meta and object languages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.4
Natural Deduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.5
2.6
2.4.1
Propositional Calculus . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.4.2
Predicate Logic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.4.3
Mathematical Induction . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.4.4
Equality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
The Sequent Calculus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.5.1
Semantics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.5.2
Backward proofs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.5.3
Additional rules for sequent calculi . . . . . . . . . . . . . . . . . . . . . 24
2.5.4
A sequent calculus for intuitionistic logic . . . . . . . . . . . . . . . . . . 24
2.5.5
Proof methodology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
The λ-calculus as a logic of computation . . . . . . . . . . . . . . . . . . . . . . 27
2.6.1
Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.6.2
Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.6.3
Reduction properties of the λ-calculus . . . . . . . . . . . . . . . . . . . 31
2.6.4
The expressive power of the λ-calculus . . . . . . . . . . . . . . . . . . . 33
2.6.5
Semantic questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
1
2
CONTENTS
2.7
References and further reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3 Typed Theories
39
3.1
Simple Type Theory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
3.2
Properties of Simple Type Theory . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.3
3.4
3.5
3.2.1
Soundness . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
3.2.2
A type-checking algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . 45
3.2.3
Weak Normalization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
3.2.4
Strong Normalization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
3.2.5
Confluence: the Church-Rosser Theorem . . . . . . . . . . . . . . . . . . 52
3.2.6
The strength of the calculus . . . . . . . . . . . . . . . . . . . . . . . . . 53
The Mathematics of U∈U . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
3.3.1
Dependent function types . . . . . . . . . . . . . . . . . . . . . . . . . . 55
3.3.2
Expressiveness of the theory of dependent types . . . . . . . . . . . . . . 57
3.3.3
Girards Paradox
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
A systematic approach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
3.4.1
Martin Löfs constructive semantic theory . . . . . . . . . . . . . . . . . . 62
3.4.2
Semantics of type-theoretical expressions . . . . . . . . . . . . . . . . . . 63
3.4.3
Judgements in Type Theory . . . . . . . . . . . . . . . . . . . . . . . . . 64
3.4.4
Propositions as types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
3.4.5
Propositional equality . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
3.4.6
A cumulative hierarchy of universes . . . . . . . . . . . . . . . . . . . . . 67
3.4.7
A calculus for proof development . . . . . . . . . . . . . . . . . . . . . . 67
3.4.8
Formal proofs in Type Theory . . . . . . . . . . . . . . . . . . . . . . . . 68
References and further reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
4 The Type Theory of NuPRL
4.1
4.2
4.3
71
Basic constructs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
4.1.1
The semantic theory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
4.1.2
The proof rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
Logic in Type Theory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
4.2.1
The empty type void . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
4.2.2
Constructive logic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
4.2.3
Classical logic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Programming in Type Theory . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
CONTENTS
3
4.3.1
Proofs as programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
4.3.2
Natural numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
4.3.3
The NuPRL type of finite lists . . . . . . . . . . . . . . . . . . . . . . . . 94
4.3.4
A programming example . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
4.3.5
Set Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
4.4
4.5
4.6
Recursive Definition
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
4.4.1
Inductive Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
4.4.2
Recursive functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
4.4.3
Infinite Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
Other types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
4.5.1
Quotients . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
4.5.2
Atom . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
References and further reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
5 Implementing Automated Reasoning
5.1
5.2
5.3
5.4
Building systems for interactive proof development . . . . . . . . . . . . . . . . 108
5.1.1
ML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
5.1.2
Implementing the object language . . . . . . . . . . . . . . . . . . . . . . 110
5.1.3
The NuPRL system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
Decision procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
5.2.1
arith: a decision procedure for elementary arithmetic . . . . . . . . . . . 117
5.2.2
Equality Reasoning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
5.2.3
Other Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
5.2.4
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
Metalevel Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
5.3.1
Tactical Theorem proving . . . . . . . . . . . . . . . . . . . . . . . . . . 126
5.3.2
Refinement tactics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
5.3.3
Transformation tactics . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
5.3.4
Validity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
5.3.5
Writing tactics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
5.3.6
Experiences. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
References and further reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
6 Building Theories
6.1
107
133
Methodology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
4
CONTENTS
6.2
Simple Theories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
6.2.1
Elementary logic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
6.2.2
Finite sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
6.2.3
Number Theory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
6.2.4
Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
6.2.5
Finite Automata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
6.2.6
Real numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
6.3
Automated Theorem Proving . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
6.4
Application to Program Construction/Development and verification . . . . . . . 136
6.4.1
6.5
program synthesis, verification,... . . . . . . . . . . . . . . . . . . . . . . 136
References and further reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
7 Advanced Topics
7.1
7.2
137
Metamathematics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
7.1.1
Expressing meta-concepts in the object language . . . . . . . . . . . . . . 137
7.1.2
Reflection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
Alternative theories (optional) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
7.2.1
Girard’s Theory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
7.2.2
The calculus of constructions . . . . . . . . . . . . . . . . . . . . . . . . 139
7.2.3
Other Type theoretic calculi . . . . . . . . . . . . . . . . . . . . . . . . . 139
7.3
How to compute well? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
7.4
References and further reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
8 Summary and future views
141
9 Glossar, Index, ToC
143
9.1
Natural deduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
9.2
Details of the type system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
9.3
The rules
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
9.3.1
Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
9.3.2
Products . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
9.3.3
Union . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
9.3.4
Booleans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
9.3.5
Sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
9.3.6
Quotients . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
CONTENTS
5
9.3.7
Atoms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
9.3.8
Unit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
9.3.9
Void . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
9.3.10 Equality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
9.3.11 Natural numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
9.3.12 Integers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
9.3.13 List
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
9.3.14 Recursive types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
9.3.15 Partial functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
9.3.16 Miscellaneous . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
9.3.17 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
9.3.18 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
9.4
Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
9.4.1
Bibliography
Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
155
6
CONTENTS
Chapter 1
Introduction
The old dream of mathematicians is to create a system that can be used to automate mathematics such that all theorems have an exact formal proof which might easily be checked to be
correct by some by algorithm.
If taken in the rigid sense this means building machines that would decide whether a statement
is provable or not, a task which can be achieved - at least in principle - for all and only the
decidable theories. For formal systems presented by recursive sets of axioms and of recursive
rules one can - at least in principle - automatically generate the theorems.
Various experiments have been carried out since the advent of computers in both directions. As
successful examples apart from the flourishing trade of commercial expert systems one could
quote MACSYMA (a giant expert system based on rewrite rules implementing algorithms
of arithmetic, algebra, and calculus) in the field of computerized symbolic computation, and
PROLOG in the field of automatic theorem provers for the Horn-Clause fragment of first-order
logic.
Evidences for the success of computerized support can also be found in other mathematical
areas like careful explanation (program verifiers), proof checking and counterexample generation ([WOLB84]), detailed case analysis in proofs (4-colours problem), structuring complex
algorithms, revealing hidden assumptions, or even “intelligent” text processing (TEX).
There is, however, a more heroic approach to automatization: to look for a system that would
both check and find proofs for all kinds of mathematics. In the words of the sixties, one tries
to be realistic by asking the impossible.
Such a system, of course, needs a very expressive language that can be used for an “implementation” of the whole bulk of mathematics within a computer. Unfortunately set theory,
the basis for modern mathematics, is highly nonconstructive and therefore inappropriate for
this purpose. A first step towards the unreachable goal, therefore, is to develop suitable constructive theories for mathematics, similar in scope and universality to classical set theory.
Some proposals are: an intuitionistic predicative set theory by Martin-Löf [ML82, ML84], the
calculus of constructions by Coquand and Huet [CH85, CH88], and Platek and Scott’s Logic
for computable functions.
The next step is to turn these universal constructive theories into automatic generic proofcheckers. This has been done with good results starting with AUTOMATH [Bru80] and a
number of successive approximations like Edinburgh’s LCF [GMW79], PPλ (later described in
7
8
CHAPTER 1. INTRODUCTION
[Pau87]) and NuPRL [CAB+ 86], currently the most sophisticated of the existing systems.
One step further is to find automatic generic theorem provers that would not only check
but also develop proofs, according to the families of logic that the system could both define and
use. Active work is currently going on in these areas and it seems to indicate that a system
like NuPRL can be used directly for this purpose [CH90b].
The path towards the automation of mathematics described in this book begins with MartinLöf’s intuitionistic predicative set theory. Today, this language is better known as Type Theory because its structure resembles ideas from the development of data types in programming
languages. As it turned out, Type Theory is even more expressive than set theory since it
properly explains the notion of “algorithm” while set theory has severe problems at that point.
Thus Type Theory can be used not only to represent “ordinary” mathematical reasoning but
also for reasoning about the properties of algorithms, particularly the correctness of programs.
The theory will be described in the formulation used by the NuPRL system which not only
checks formal proofs but can also be used for interactively developing them which in particular
means that type theory can be used for program development. Implementation aspects such
as these, as we will see, have a major influence on the formulation of the theory itself.
Mechanisms for automating the proof development process will also be discussed. The concept
of tactics, which goes back to Edinburgh’s LCF system [GMW79], allows to program the
application of inference rules in an otherwise fully interactive system. From a theoretical
point of view tactics are one means of representing the metalevel of type theory by algorithms.
Although the metalevel can not be a part of the inference system itself large components of
it can be accessed by formalizing the metamathematics of Type Theory within Type Theory.
Besides drastically reducing the size of proofs this will allow reasoning about proofs as humans
often do.
1.1
Outline
Chapter 2 begins with a general introduction to formal calculi for logic and computation. In
particular we will present the sequent calculus for mathematical reasoning and the λ-calculus as
a model of computation. Both should be considered as necessary prerequisites for understanding
Type Theory.
We will begin the discussion of Type Theory in Chapter 3 with two historically important
predecessors which contain the same basic principles and are much simpler than Martin-Löf’s
full theory of types. Unfortunately the first one is not expressive enough while the second one
contains a paradox. Section 3.4 therefore presents a systematic approach to the development
of type theory which we will follow in the rest of this book. Chapter 4 explains the type theory
of NuPRL,....basic concepts, those coming from the desire to catch the notion of propositions,
and inductively defined structures.
......
1.2. REFERENCES AND FURTHER READING
1.2
9
References and further reading
The book about the NuPRL System [CAB+ 86] will serve as a reference. Also Martin-Löf’s
book on Type Theory [ML84] ....
[And86, Bac89, BCM88a, Bis67, CAB+ 86, Con88, GLT89, vBJ77, Kle52, ML84, Pol45, Pra65,
Sch85, Ste72, Tur84]
[CHS72], chapter 17
Set Theory [Ber68, Qui63, Sup72] How [Pol45, Sch85]
10
CHAPTER 1. INTRODUCTION
Chapter 2
Logic and computation
This chapter is intended to provide mathematical preliminaries which are needed or at least
helpful to understand methods for machine support when dealing with mathematics and programming. We will give an introduction to formal proofs, first order logic, natural deduction,
the sequent calculus, and - as a model of computation - the λ calculus. We will do so with
increasing levels of formality. The discussion of semantics is brief and informal; the emphasis
is how to make use of formal systems.
2.1
Formal Calculi
A formal logic or calculus is a syntactic game for producing symbolic objects according to given
rules. Sometimes the motivation of the rules is vague but usually they are derived with respect
to a well understood meaning or semantics.
Most (formal) mathematical theories are interpreted in set theory: each term corresponds to
a set; each rule corresponds to a fact about sets. Set theory is taken to be the foundation of
everything else. Its axioms are justified by informal but widely accepted intuitions like “sets
exist; the union of two sets is a set”. However, when relying on intuition one must be extremely
careful. At the beginning of this century Russel’s Paradox demolished the prevailing notion of
set, together with years of Frege’s work.
Formal logics free logicians from the slippery ambiguities of human language.
A formal logic comprises assertions and inference rules. The assertions A, B, C, ... express
meaningful statements while an inference rule has the form “from A1 and ... and An conclude
B” for n ≥ 0. The usual convention is to write this as
A1 , A2 , ... , An
B
The assertions A1 , A2 , ... , An are the premises of the rule and B is the conclusion. Theorems
are those assertions theat can be proved by applying inference rules to other theorems. In order
to have any theorems ther must be at least one axiom, a rule with no premises. A proof can be
written as a tree whose branches are the rules and whose leaves are axioms.
Inference rules allow formal proofs to be constructed without having to think about the meaning
of a formula. Thus machines can prove theorems. But we must be aware of a difference between
11
12
CHAPTER 2. LOGIC AND COMPUTATION
provability and truth. Ideally every theorem should be true and every (semantically) true fact
a theorem. An inference rule is sound if its conclusion is true provided every premise is true. If
every inference rule is sound then every theorem of the calculus is true. Otherwise the calculus
is of little value. A calculus is complete if every true assertion has a formal proof. Completeness
is usually unattainable: Gödel demonstrated that no logic allowing nontrivial reasoning about
arithmetic can be complete. 1
It should also be mentioned that a proof calculus explains only the rules how proofs have to be
elaborated in order to make sure that they are correct. It is not by itself a method about how
to find proofs.
2.2
First Order Logic
First Order Logic is the most familiar language for mathematics.
2.2.1
Syntax
Typically the set of assertions in a calculus is described by a grammar: each assertion is
constructed from atomic symbols using logical connectives.
Terms denote mathematical values such as sets, functions, or numbers. Let there be an infinite
set of variables and, for each n ≥ 0 a set of n-place function symbols. A term is a variable of a
function application f (t1 , .., tn ) where f is an n-place function symbol and t1 , .., tn are terms.
A 0-place function symbol is a constant symbol; the term c() is usually written c2 .
The assertions of first order-logic, called formulae are built up from terms. Let there be a set
of n-place predicate symbols for each n ≥ 0. An atomic formula has the form P (t 1 , .., tn ) where
P is an n-place predicate symbol and t1 , .., tn are terms. A formula is either an atomic formula
or one of ¬A, A B, A B, A ⇒ B, ∀x.A, ∃x.A or (A), where A and B are formulae and
x is a variable. Every formula thus contains at least one predicate symbol.
There are some conventions for abbreviated writing of formulae.
The bi-implication A ⇔ B abbreviates (A ⇒ B) ∧ (B ⇒ A). Precedence conventions lessen the
need for parentheses in formulae. The symbol ¬ binds most tightly, followed by ∧ , ∨ , ⇒ , and
⇔ in decreasing order. The scope of a quantifier extends as far to the right as possible. One
quantifier can bind several variables at once.
2.2.2
Semantics
The semantics of first order logic is usually expressed in set theory. An interpretation or model
assigns a mathematical value to each symbol. Variables, functions, and predicates are all defined
with respect to a fixed set (or universe). Each variable is assigned an element of the universe;
1
The differential calculus is indeed a formal calculus. It has expressions like du/dx and rules like (d/dx)(uv)=
udv/dx + vdu/dx. Each expression and rule has a complicated mathematical justification but the rules may
be used long after their justification has been forgotten
2
This does not mean that the constant symbol c is to be identified with the term c. It is only an abbreviation.
2.3. META AND OBJECT LANGUAGES
13
each n-place function symbol is assigned a function on the universe; each n-place predicate
symbol is assigned an n-place relation over the universe.
Under an interpretation, each term has a value and each atomic formula is either true or false.
The truth of the other formulae is determined as follows:
The
The
The
The
The
The
negation ¬A is true if A is false.
conjunction A ∧ B is true if both A and B are true.
disjunction A ∨ B is true if either A or B is true.
implication A ⇒ B is true if B is true provided A is.
universal quantification ∀x.A is true if A is true for every x
existential quantification ∃x.A is true if A is true for some x
Propositional logic is the logic of the connectives ¬, ∧ , ∨ , ⇒ . Adding quantifiers gives first
order logic, sometimes called the predicate calculus. Adding quantifiers over formula variables
gives higher order logic.
2.3
Meta and object languages
Consider statements we might make about formulae like “The conjunction of a formula with the
conjunction of two other formulae implies the conjunction of the first and the second formula
with the third”. While this is a perfectly legal statement it is hardly readable. Readable
statements must use symbols from the logic itself: “the formula A ∧ (B ∧ C) implies (A ∧ B) ∧ C”.
Clearly, this does not mean that the symbol “A” is itself a formula. A is just a name for a
formula. We must not confuse an object (a formula) and its name (A) in a statement about
formulae.
To clear up this confusion we have to distinguish the meta language from the object language.
The formal language of terms and formulae is the object language while any statement about
the object language is made in the meta language. Here the meta language is English augmented with mathematical notation: symbols from the object language, proof trees, and names
for object language expressions which we also call syntactic meta variables. We will use the
following conventions:
• names of formulae include A, B, C
• names of terms include r, s, t, u
• names of predicates symbols include P, Q, R
• names of function symbols include f, g, h
• names of object variables include x, y, z
A syntactic meta variable must never be used as an object language symbol. Object language
expressions will therefore be written in typewriter font.
Inference rules are described as rule schemata using syntactic meta variables:
14
CHAPTER 2. LOGIC AND COMPUTATION
A B
A ∧B
This stands for the infinite set of inferences obtained by replacing A and B by actual formulae
from the object language.
2.4
Natural Deduction
Natural Deduction is a proof calculus designed to mirror human patterns of reasoning. For each
logical connective like ∧ there are two kinds of rules
• An introduction rule answers the question “what are the conditions for concluding A ∧ B?”
• An elimination rule answers the question “what can we conclude from A ∧ B?”
A ∧ B is fully characterized by answering these two questions. Generally, elimination rules are
inverses of the introduction rules: Introducing A ∧ B then immediately eliminating it neither
gains nor loses information.
Often one connective can be expressed in terms of others. In classical logic, for instance, all the
connectives can be expressed in terms of ∧ , ∀, and ¬. But the natural deduction rule for one
connective does not mention others. In a proof, each inference involves only one connective.
In natural deduction certain rules discharge an assumption of a premise. The set of assumptions
changes during the proof: “to prove A ⇒ B assume A and prove B” The premise of a rule is
not a formula but a proof tree with a formula at the root and assumptions in the leaves.
There is a complete search procedure for first order logic. If an assertion can be proved then a
proof for it will be found3 . In propositional logic this method always terminates thus answering
the question whether the assertion is true or not while it may fail to terminate for assertions
in full predicate logic. Essentially the method is to “break down” assumptions by elimination
rules and then “build up” conclusions from smaller ones via introduction rules.
Intuitionism is a school of the philosophy of mathematics that question principles of classical
logic. It demands a constructive interpretation of the quantifiers: to prove ∃x.A one must
be able to construct a value x satisfying A. In Intuitionistic Type Theory proving ∃x.A even
constructs a function which computes x. The potential applications to the specification and
synthesis of programs are attracting attention. See chapters 4.3 and 6 for further discussion.
Although dealing with classical logic as well natural deduction has an intuitionistic orientation.
Classical deduction requires an additional rule and much additional thought.
2.4.1
Propositional Calculus
We will now briefly discuss the rules for connectives in propositional logic.
3
See [Gal86]
15
2.4. NATURAL DEDUCTION
Conjunction
The conjunction A ∧ B is true if both A and B are true. The introduction rule ( ∧ -intro) states
when A ∧ B can be concluded
A B
( ∧ -intro)
A ∧B
There are two elimination rules stating the consequences of A ∧ B
A ∧B
A ∧B
( ∧ -elim-1)
( ∧ -elim-2)
A
B
It is not hard to see that these rules capture informal reasoning about conjunction.
Putting the rules together yields proof trees such as
A ∧B
A
A ∧B
B
B ∧A
which is a proof of
A ∧B
( ∧ -commutativity)
B ∧A
This is a derived rule since the formula B ∧ A has been proved under the assumption A ∧ B.
A ∧B
Another derived rule is
[A, B]
C
( ∧ -elim-3)
C
∧ -elim-3 can be viewed as an alternative rule for conjunction elimination: If A ∧ B is true, then
so are A and B. It is, therefore, sound to assume them when proving something else. The
square brackets around A and B indicate that these assumptions are discharged from the proof
of C when the rule is applied. Given a proof of A ∧ B, and one of C from A and B, the rule
concludes C.
Exercise 2.4.1
1. Derive the rule
∧ -elim-3
A
A
(A ∧ B) ∧ C
A ∧ (B ∧ C)
2. Derive the rule
3. Derive the rule
Exercise 2.4.2 Show how to transform every proof that uses
∧ -elim-1
and
∧ -elim-2,
(identity)
( ∧ -associativity)
∧ -elim-3
into one that uses only
and conversely
Disjunction
The disjunction A ∨ B is true if either A or B is true. Two introduction rules state that A ∨ B
can be concluded from either A or B
A
B
( ∨ -intro-1)
( ∨ -intro-2)
A ∨B
A ∨B
16
CHAPTER 2. LOGIC AND COMPUTATION
[A] [B]
A ∨B C C
( ∨ -elim)
C
4
If C follows from A and C follows from B and either A or B is true then C is true.
Eliminating A ∨ B means to do a case analysis
Exercise 2.4.3
1. State and derive the rule
∨ -commutativity
2. State and derive the rule
∨ -associativity
3. Derive the distributive laws
(A ∨ C) ∧ (B ∨ C)
(A ∧ B) ∨ C
(A ∧ C) ∨ (B ∧ C)
(A ∨ B) ∧ C
(A ∧ B) ∨ C
(A ∨ C) ∧ (B ∨ C)
(A ∨ B) ∧ C
(A ∧ C) ∨ (B ∧ C)
Implication
The implication A ⇒ B is true if B is true provided A is.
The introduction rule states that if B follows from A then A ⇒ B can be concluded. It is called
the discharge rule because it discharges the assumption A. The elimination rule is Modus
Ponens.
[A]
A⇒B A
( ⇒ -intro)
( ⇒ -elim)
B
B
A⇒B
Example 2.4.1
Here is a proof for ((A ∧ B) ⇒ C) ⇒ (A ⇒ (B ⇒ C))
(A ∧ B) ⇒ C
[A] [B]
A ∧B
C
B ⇒C
A ⇒ (B ⇒ C)
The assumptions A and B are discharged at different times: first B, then A. Some authors
use therefore labels to keep track of which instance of a rule discharges each assumption. A
formalized method for that is the sequent calculus which we will introduce in section 2.5.
Exercise 2.4.4 Derive the following rules
A ⇒ (B ⇒ C)
(A ∧ B) ⇒ C
(A ⇒ B) ∧ (A ⇒ C)
A ⇒ (B ∧ C)
(A ∨ B) ⇒ C
(A ⇒ C) ∧ (B ⇒ C)
(A ⇒ C) ∧ (B ⇒ C)
(A ∨ B) ⇒ C
Exercise 2.4.5 Explain why the introduction and elimination rules for ⇒ are sound.
4
This is not the same as “C follows from A and B”
17
2.4. NATURAL DEDUCTION
Negation
The negation ¬A is true if A is false. What could be simpler or more problematical than
falsehood? Prawitz [Pra65] in his formulation of first order logic represents falsehood by a term
Λ which stands for contradiction. ¬A then simply abbreviates A ⇒ Λ. This view of negation is
sound for both intuitionistic and classical logic.
The rules for negation thus are special cases of those for implication: if assuming A leads to a
contradiction then ¬A can be concluded and, by ⇒ -elim, ¬A and A lead to a contradiction:
[A]
Λ
¬A
(¬-intro)
¬A
A
Λ
(¬-elim)
Contradiction
The rules so far yield minimal logic, where Λ is just another symbol. If we want Λ to express
contradiction we have to give rules making Λ behave accordingly.
The essential property of contradiction are illustrated by the laws of arithmetic. The assumption
0 = 1 implies every numeric equation. Thus a contradiction should imply every formula.
Depending on the mathematical philosophy there are two ways of expressing this in a contradiction rule: The classical interpretation is, if ¬A leads to a contradiction then we may conclude
A.
[¬A]
(ΛC-elim)
Λ
A
In intuitionistic logic contradiction is taken more literally which leads to a weaker contradiction
rule. A can be concluded only if Λ can be derived directly:
Λ
(ΛI-elim)
A
Obviously there can be no introduction rule for Λ since no set of premises (not involving Λ)
can imply Λ.
The contradiction rule is the only difference between classical and intuitionistic natural deduction logics. However, classical reasoning in natural deduction is not really natural unless some
derived rules are used along with the primitive ones. To prove A it may be necessary to derive
a contradiction from assuming ¬A.
¬¬A
(¬¬-elim)
A
It is this double negation rule which - together with other derived deduction rules - causes the
vast difference between classical and intuitionistic reasoning.
Exercise 2.4.6 Explain why “A implies contradiction” means the same as “not A”
Exercise 2.4.7 Once we have a symbol for contradiction we can define a symbol T for truth by
stating formal theorems containing no meta variables and depending upon no assumptions. Give
three examples.
18
CHAPTER 2. LOGIC AND COMPUTATION
Exercise 2.4.8
¬¬A
A
A ∨ ¬A
Derive the following rules for classical logic
(¬¬-elim)
(excluded middle)
¬(A ∨ B)
¬A
¬(A ∧ B)
¬A ∨ ¬B
(¬ ∨ -elim-1)
¬A ∨ ¬B
¬(A ∧ B)
¬(A ∨ B)
¬B
(¬ ∨ -elim-2)5
¬(A ⇒ B)
A
Exercise 2.4.9 Prove ¬¬(A ∨ ¬A) without using the classical contradiction rule. 6
2.4.2
Predicate Logic
Analysis, the field of mathematics underlying the differential calculus, offers many examples
of quantification. “If is arbitrary such that P () holds, then there exists some δ such that
Q(, δ)”. Quantifiers are obviously indispensible but require great care. The semantics becomes
more complicated: what is an arbitrary value. New issues arise: substitution, free and bound
variables. Propositional logic is decidable but predicate logic is not.
Let P be a 1-place predicate symbol. In the semantics ∀x.P (x) is true whenever P can be
interpreted as a predicate that holds true for all values. In the formal calculus, if ∀x.P (x) is a
theorem and t is a term then P (t) is a theorem. However, the correspondence between “∀x.P (x)
holds” and “P (t) holds for every term t” is imperfect because the model may contain values
that are not expressed by any term. If, for instance, the universe is the set of all real numbers,
and the function symbols are the ordinary decimal numerals and arithmetic operators, then
there are only countably many terms but uncountably many real numbers. Also the semantics
of ∀x.P (x) may strongly depend on the universe. ∀x.∃y.x < y < x + 1 is true when considering
rational numbers but false within the universe of natural numbers.7
Substitution
Let in the following A be a formula containg a variable x. The formula ∀x.A asserts that A is
true for every assignement of a value to x. Each theorem that follows from ∀x.A is obtained
by substituting a term t for x in A. We will need to be precise about what substituion means,
but let us first introduce some notation:
If A is a formula, t a term, and x a variable, then A[t/x] is the formula that results from
substituting t for x in A8 . Read A[t/x] as “A putting t for x”. If we simultaneously substitute
t1 for x1 , ... and tn for xn in A we write A[t1 /x1 , ..., tn /xn ]. Observe that this is not the same
as iterated substitution. Substitution on terms is defined correspondingly.
The substitution notation belongs to the meta language, not to the object language of the logic.
The formula A[t/x] does not literally contain the symbols [, /, ] or A. Rather it is the result of
substitution in a formula denoted by A.
5
The ¬ ∨ -elim rules hold in intuitionistic logic as well
In fact, every propositional formula A can be proved in classical logic if and only if ¬¬A can be proved in
intuitionistic logic [Dum77].
7
Pure predicate logic cannot handle this properly. We need a typed logic for that
8
Unfortunately there is also a convention of writing A[x \ t] for the same
6
2.4. NATURAL DEDUCTION
19
In ∀x.A the variable x is said to be bound. The name x is not significant: the bound variable can
be renamed provided that all its occurrences in A are correspondingly renamed. The formula
∀x.A is logically equivalent to ∀y.A[y/x].
A bound variable must sometimes be renamed prior to substitution. If x and y range over
the natural numbers then ∀x.∃y.x 6= y is a true formula. Substituting y for x, it is wrong to
conclude ∃y.y 6= y. The problem is the capture of a free variable: the free variable y comes
into the scope of ∀y and turns into a bound variable. The cure is to define what it means for
a variable to occur free or bound in a term and to restrict substitution accordingly.
In section 2.6 and in the chapters about Type Theory we will give precise definitions of free
and bound variables and substitution. The corresponding definitions for first order logic follow
the same pattern and we will not discuss them here.
The semantics of quantifiers
In order to understand the rules for a symbol it is essential to know its meaning. We have
ommitted discussing the semantics of the familiar connectives ∧ , ∨ , ⇒ , ¬. But a brief look
at the semantics of quantifiers will make the rules easier to understand. See a logic textbook
[Gal86, MW85] for a rigorous treatment.
A formula A is valid if it is true in every interpretation and for every assignement of values
to its free variables. So A is valid if and only if ∀x.A is valid, regardles of whether x is free
in A. Thus A should count as a proof of ∀x.A. Proofs depending upon assumptions require
something stronger:
Theorem 2.4.2
If the variable x is not free in B, then B ⇒ A is valid if and only if
B ⇒ (∀x.A) is valid.
Given assumptions A1 , ..., An where x is free in no assumption, let B be A1 ∧ ... ∧ An in the above
theorem. If the assumptions A1 , ..., An imply A then they imply ∀x.A.
To frame a rule of existential elimination, we need to characterize the logical consequences of
an existential formual:
Theorem 2.4.3
If the variable x is not free in B, then A ⇒ B is valid if and only if
(∃x.A) ⇒ B is valid.
Given a formula C and assumptions A1 , ..., An where x is free in no assumption nor C, let B
be A1 ∧ ... ∧ An in the above theorem. If A and the assumptions A1 , ..., An imply C then ∃x.A
and those assumptions imply C.
Exercise 2.4.10 Prove the theorems 2.4.2 and 2.4.3
The universal quantifier
The universal quantification ∀x.A means that A is true for every x. The introduction rule
(generalization), justified by theorem 2.4.2 states that if A is a theorem and x is an arbitrary
variable then ∀x.A is a theorem:
20
CHAPTER 2. LOGIC AND COMPUTATION
A
∀x.A
The rule is subject to a proviso: the conclusion holds if the proviso is satisfied.
Provided x is not free in the assumptions of A
(∀-intro)
The elimination rule (specialization) states that if ∀x.A is a theorem an t is a term then A[t/x]
is a theorem.
∀x.A
(∀-elim)
A[t/x]
Exercise 2.4.11
1. Prove (∀x.A ∧ B) ⇔ (∀x.A) ∧ (∀x.B)
2. Prove (∀x.A ⇒ B) ⇔ A ⇒ (∀x.B) provided x is not free in A
3. Prove (∀x.A) ∨ (∀x.B) ⇒ (∀x.A ∨ B)
4. Show that (∀x.A) ∨ (∀x.B) does not follow from (∀x.A ∨ B)
The existential quantifier
The existential quantification ∃x.A means that A is true for soem x. The existential introduction
takes this value from a term t
A[t/x]
(∃-intro)
∃x.A
The elimination rule is justified by theorem 2.4.3:
[A]
B
∃x.A
(∃-elim)
B
provided x is not free in B nor in the assumptions of B apart from A
Exercise 2.4.12
1. Prove (∃xy.A) ⇔ (∃yx.A)
2. Prove
A⇒B
(∃z.A) ⇒ (∃z.B)
provided z is not free in the assumptions of A ⇒ B
3. Prove (∃x.A) ∧ B ⇔ (∃x.A ∧ B) provided x is not free in B
4. Prove in classical logic (∃x.A ⇒ B) ⇔ (∀x.A) ⇒ B provided x is not free in B
2.4.3
Mathematical Induction
Many parts of mathematics deal with inductively defined objects like natural numbers. Reasoning about these involves mathematical induction:
If P (0) is true and if P (x) implies P (x + 1) for every natural number x then P (x) is
true for for every natural number x.
2.4. NATURAL DEDUCTION
21
Within the universe (c.f. section 2.2.1) of natural numbers this principle is expressed by the
following formal rule:
A[0/x] ∀x.(A ⇒ A[x + 1/x])
∀x.A
However, this rule involves quantifiers in addition to the induction principle. Following the philosophy of natural deduction, a rule should mention as few constructs as possible. Fortunately,
the rule
[A]
A[0/x]
A[x + 1/x]
(IN-induction)
A[t/x]
is as powerful as the previous one and often allows shorter proofs.
Mathematical induction is not restricted to natural numbers. For other recursive structures
like lists and trees there is a similar principle structural induction. We will discuss both in more
detail in Section 4.4.
2.4.4
Equality
Dealing with equality is essential for reasoning about mathematical objects and their values.
Equal terms can be substituted for each other in terms and predicates and term rewriting could
not properly be defined without a notion of equality.
The equality predicate, usually denoted by “=”, is an equivalence relation because it satisfies
three fundamental laws. It is reflexive, symmetric, and transitive. The corresponding rules are:
s=t t=u
t=u
(Symmetry)
(Transitivity)9
(Reflexivity)
t=t
u=t
s=u
The congruence law of a function states that equal arguments give equal results. Adding
equality to a logic thus requires a congruence axiom for every function symbol. If f is an
n-place function symbol then
t1 = u 1 . . . tn = u n
(Congruence rule for f )
f (t1 , .., tn ) = f (u1 , .., un )
needs to be added as a rule. This can lead to a huge set of rules. A way of asserting the
congruence laws for all functions at once is by adding substitution rules for terms:
t=u
(Substitution on terms)
s[t/x] = s[u/x]
It states that if t equal u then any term constructed from t equals the term constructed similarly
from u. The term s serves as a template for substitution of terms at occurrences of the variable
x.
Exercise 2.4.13 Prove the congruence rule for a 3-place function symbol f from the substitution
rule
9
Actually this is a redundant rule system since symmetry and transitivity follow from reflexivity and substitution. Consider, for instance, P [x] ≡ x = s. Then P [s/x] follows from reflexivity and symmetry from
substitution s = t ⇒ t = s ≡ P [t/x]
22
CHAPTER 2. LOGIC AND COMPUTATION
Note that the substitution rule can not be derived once and for all from all the congruence
rules since each term s requires a different proof tree.
On formulae the bi-implication ⇔ assumes the same role as equality on terms. ⇔ is an
equivalence relation and for all the logical connectives one can prove congruence laws like
A⇔B C ⇔D
A ∧C ⇔ B ∧D
For predicates, as well as functions, equal arguments should yield equal results. Similarly, we
must add a congruence law for every n-place predicate symbol P :
t1 = u 1 . . . tn = u n
(Congruence rule for P )
P (t1 , .., tn ) ⇔ P (u1 , .., un )
A rule for substituting equal terms in formulae reduces the set of necessary rules. We may
conclude A[u/x] from A[t/x] and t = u
t = u A[t/x]
A[u/x]
(Substitution on formulae)
Exercise 2.4.14
1. State and prove the equivalence rules for ⇔
2. Prove the congruence laws of the logical connectives with respect to ⇔
3. = itself is a predicate symbol. Prove the congruence axiom for =
2.5
The Sequent Calculus
Reasoning in natural deduction requires to be precise about assumptions and discharging them.
Writing an assumption above a proof and later crossing it off again is in fact natural but it is
easy to get confused about which assumptions are still in force.
In a sequent calculus, the current set of assumptions is listed at every line of the proof. A
sequent A1 , ..., A ` C means that C depends upon the set of assumptions {A1 , ..., An }. The
sequent A ` A represents the assumption of A.
Each proof in natural deduction can be reworked using sequents. Example 2.4.1 becomes
A`A B`B
(A ∧ B) ⇒ C
A, B ` A ∧ B
A, B ` C
A ` B ⇒C
A ⇒ (B ⇒ C)
Sequents require a notation for sets. Let Γ, ∆ and Θ be syntactic meta-variables for sets of
formulae. The union of sets is written with a comma, set brackets are omitted: write A 1 , ..., An
instead of {A1 , ..., An } and Γ, A instead of Γ∪{A}. The conjunction introduction rule ( ∧ -intro)
becomes:
Γ`A ∆`B
Γ, ∆ ` A ∧ B
23
2.5. THE SEQUENT CALCULUS
i.e., the conclusion depends upon every assumption fo A and B.
To express the discharge of an assumption A it is conventional to partition the assumptions
into A and a set ∆ not containing A. ∨ -elim thus becomes:
Γ ` A ∨ B ∆, A ` C Θ, B ` C
Γ, ∆, Θ ` C
2.5.1
Semantics
There is an obvious correspondence between a natural deduction proof tree with root C and
leaves A, B and the sequent proof with root A, B ` C and leaves A ` A and B ` B. However,
the sequent calculus is more than just a different notation for natural deduction, since any
sequent can be the premise or conclusion of a proof. Thus a sequent must be an assertion in
its own right.
Let Γ be a set of formulae and A be an individual formula. The sequent Γ ` A means that A
is true provided every member of Γ is true. When there are no assumptions then ` A means
that A is true.
Many authors view the sequent calculus as a meta logic about provability: Γ ` A then means
that A can be formally derived from Γ, and ` A means that A is a theorem. ` belongs to the
meta language of the calculus. In this book, Γ ` A is an object language assertion which, like
any assertion, maybe false. ` A is false if A is false.
The semantic justification of a sequent follows that of the corresponding natural deduction rule.
Exercise 2.5.1 Give semantical justifications for the above
2.5.2
∧ -intro
and
∨ -elim
rules
Backward proofs
Inference rules given so far are designed for forward proofs: working from known theorems to
new ones. The ( ∧ -intro) rule, for instance, given A and B concludes A ∧ B, forming the union
of the assumptions.
In normal mathematics we often proceed in the opposite way: starting with a desired conclusion,
or goal, we work backwards from goals to subgoals. For instance, to prove A ∧ B, we have to
prove A and B. Since we cannot predict which assumptions are necessary to prove A or to
prove B we use the same assumptions for the premises and the conclusion:
Γ`A Γ`B
Γ ` A ∧B
From now on we are concerned with backwards proofs exclusively. Proof trees are constructed
starting from the root working towards the leaves. A rule takes a goal and produces subgoals
rather than taking premises and producing a conclusion. The logical meaning of “rule” and
“proof” is the same as before; we are merely changing perspective, emphasizing the process of
constructing a proof.
The above form of rules is somewhat misleading. It still suggests forward inferences. We will
therefore use a graphical form which represents the top down style of proof construction better:
24
CHAPTER 2. LOGIC AND COMPUTATION
Γ ` A∧B
by
∧ -intro
· Γ ` A
· Γ ` B
This is also a form which can easily be represented on a computer.
2.5.3
Additional rules for sequent calculi
The cut rule allows a proof to be structured into lemmata. When trying to prove C, the lemma
L can be added to C’s assumptions, provided it can be proved
Γ ` C
by cut L
· Γ ` L
· Γ,L ` C
The cut rule can be derived from the
∨ -elim
and
∨ -intro
rules given below.
A thinning or weakening rule allows to get rid of a set Θ superfluous assumptions:
Γ ` C
by thinning Θ
where ∆ = Γ \ Θ
· ∆ ` C
A rule derived from thinning is a general assumption rule
Γ ` C
by assumption
where C ∈ Γ
In a typical sequent calculus introduction rules operate on the right hand side of the assertion
sign (`) where elimination rules operate on the left hand side. The formula being eliminated is
assumed in the conclusion and the elimination rules illustrate how to handle the assumptions,
especially, when to delete an assumption. Sometimes the rules are called left or right rule instead
of elimination or introduction rule.
2.5.4
A sequent calculus for intuitionistic logic
We give the rules only.
Conjunction
Γ ` A∧B
by
∧ -intro
· Γ ` A
Γ,A ∧ B ` C
by
∧ -elim
· Γ,A,B ` C
· Γ ` B
The ∧ -elim rule is based on the natural deduction rule
it from A and B instead.
∧ -elim-3:
to prove C from A ∧ B, prove
25
2.5. THE SEQUENT CALCULUS
Disjunction
Γ ` A ∨B
by
∨ -intro-1
Γ ` A ∨B
· Γ ` A
by
Γ,A ∨ B ` C
∨ -intro-2
· Γ ` B
by
∨ -elim
· Γ,A ` C
· Γ,B ` C
Implication
Γ ` A⇒B
Γ,A ⇒ B ` C
by ⇒ -intro
· Γ,A ` B
by ⇒ -elim
· Γ,A ⇒ B ` A
· Γ,B ` C
⇒ -elim has little resemblance to modus ponens: to prove C from A ⇒ B first prove A then C
from B. The assumption A ⇒ B is redundant in the second subgoal but not in the first.
Negation and Intuitionistic Contradiction
Γ,Λ ` C
Γ ` ¬A
by Λ-elim
by ¬-intro
Γ,¬A ` C
· Γ,A ` Λ
by ¬-elim
· Γ,¬A ` A
· Γ,Λ ` C
The rules for negation are instances of the corresponding rules for ⇒ and Λ.
Universal Quantifier
Γ ` ∀x.A
by ∀-intro
Γ,∀x.A ` C
provided x is not free in Γ
· Γ ` A
by ∀-elim t
· Γ,∀x.A, A[t/x] ` C
∀x.A is retained in the subgoal beacause it may be needed again.
Existential Quantifier
Γ ` ∃x.A
by ∃-intro t
Γ,∃x.A ` C
· Γ ` A[t/x]
by ∃-elim
provided x is not free in Γ or C
· Γ,A ` C
Mathematical Induction
Mathematical induction is the same as before
Γ ` A[t/x]
by IN-induction
· Γ ` A[0/x]
· Γ,A ` A[x + 1/x]
provided x is not free in Γ
26
CHAPTER 2. LOGIC AND COMPUTATION
Equality
As we have seen before, equality is best described by the rules for substituing equal terms and
the reflexivity, symmetry, and transitivity rules
Γ ` A[t/x]
by substitute t=u in A
· Γ ` A[u/x]
· Γ ` t=u
Γ ` t=t
by reflexivity
Γ, t=u, u=s ` t=s
Γ, s=t ` t=s by symmetry
by transitivity
Exercise 2.5.2
Give semantical justifications for the rules of the intuitionistic sequent calculus
Exercise 2.5.3
Derive the rule Γ,A,¬A ` C
by Λ¬-elim
Exercise 2.5.4 Adding the classical contradiction rule to the intuitionistic sequent calculus would
make it classical. State this rule and derive laws for classical logic corresponding to those in exercise
2.4.8
Exercise 2.5.5
2.5.5
Derive Pierce’s law ((A ⇒ B) ⇒ A) ⇒ A in classical logic
Proof methodology
A proof calculus consists only of rules which can ensure the correctness of a mathematical proof.
There are, however, some general guidelines on how to find a formal proof for a given problem.
We give a few hints about proofs in the sequent calculus. Most of these are incorporated in the
proof tactics which we will discuss in section 5.3.1.
Work backwards from the goal building a proof tree top down. Use elimination rules to break
down formulae on the left; use introduction rules to break down the formula on the right.
Assumption and contradiction rules terminate branches of the proof tree.
If more than one rule applies, it rarely matters which one applies first. For intuitionistic
deduction avoid using ∨ -intro rules before ∨ -elim rules. Otherwise one may end up with false
subgoals.
In backward proofs the rules ∃-intro and all-elim should never be used before ∃-elim and ∀-intro.
The former may put free variable into the goal, violating the provisos of the latter.
When the above constraints leave a choice of rules, choose the one that produces the fewest
subgoals.
Quantifier reasoning involves the correct choice of a term t to be substituted for a variable x.
The value of t can be determined only by completing the proof, yet the proof cannot proceed
until a value for t is supplied. This situation can only be resolved by user interaction. In general,
a full automation of the proof is not possible without making use of meta-logical techniques
before executing the proof10
10
Resolution theorem provers can determine t by unification during the proof. Using resolution-like techniques
to analyze the goal a term t to be supplied in quantifier rules can be determined beforehand
2.6. THE λ-CALCULUS AS A LOGIC OF COMPUTATION
27
The use of induction requires real intelligence. An induction rule can be applied to any goal
but rarely leads to a proof. Often a proof of a formula requires induction on some stronger
formula: the induction step requires the stronger induction hypothesis.
2.6
The λ-calculus as a logic of computation
Among the existing calculi for formal reasoning about programs the λ-calculus is the most
simple one. It has very few constructs and thus it is easy to prove theorems about the calculus
itself. Nevertheless it is rich enough to express all the computable functions. This means that
all the programming languages we might be interested in can be expressed in terms of the
λ-calculus.
As a formal system, the λ-calculus can be used for studying ways in which functions can be
formed (defined), combined (applied) and used for computation. Unlike set-theoretic accounts
of functions, the λ-calculus takes an intensional view of functions. Functions are understood
as computation rules for establishing a correspondence between an object, the argument of
the function, and another object, the value or result. The process of using the rule to obtain
the correspondence is called function application. Arguments and results of functions can be
arbitrary expressions, including other functions, which makes the λ-calculus a calculus for
higher order functions. The basic objects in λ-calculus are λ-terms and the notation for these
objects reflects the above viewpoint.
2.6.1
Syntax
Let there be a countable set of symbols called variables11
Definition 2.6.1
λ-terms are defined inductively by the following clauses
1. If x is a variable then x is a λ-term.
2. λ-abstraction: If b is a λ-term and x is a variable then λx.b is a λ-term.
3. Application: If f and t are λ-terms then so is f (t)
λ-abstraction allows us to express a function without having to give it a name. In λx.b the x
is the formal argument to the function and b represents its body.
Example 2.6.2 In mathematical textbooks we often find definitions like “let f (x) = 2x”.
What is really intended was to say “define a function f by f (x) = 2x”. Using λ-calculus we
express this in a brief and mathematical correct form as “let f = λx.2x”.
The name f is rather unimportant. It is the behaviour of f which really counts and λx.2x is
all we need to express it.
11
In pure λ-calculus there is no need for constants. In practical applications, however, it may be convenient
to have them available.
28
CHAPTER 2. LOGIC AND COMPUTATION
Note that the functions defined in the λ-calculus are one-place functions. This is not really
a restriction because functions which take several arguments can be expressed in terms of
functions of a single argument: Suppose f is a function of two arguments x and y, then we
may think of f as a function of a single argument x which returns as a value another function
taking y as its single argument. Thus, instead of writing f (x, y) we simply write f (x)(y).
This representation is called currying12 and f is called a curried function. In the λ-calculus all
functions are written in curried form unless we use abbreviations.
Terms in the formal syntax are unambiguous but lengthy. The convention is to omit brackets
when the meaning is clear and to write f xy for (f (x))(y) assuming associativity to the left.
Also a sequence of λ’s can be abbreviated with a single one, writing λxy.t instead of λx.λy.t.
2.6.2
Evaluation
To use the λ-calculus as a computation formalism we need to describe what happens when
a λ-term is applied to an argument. Roughly speaking, when the λ-term λx.t is applied to
an argument a the occurrences of x in t are replaced by a. In the previous sections we have
accepted this informal description. We will now make it more precise by defining the concept
of free and bound occurrences of variables in expressions:
Definition 2.6.3
lowing rules:
Bound and free occurrences of variables are defined inductively by the fol-
1. In x, x occurs free, no other variables occur at all.
2. In λx.f all the free occurrences of x in f become bound. Free occurrences of variables y
different from x remain free in λx.f .
“λx.” is called a binding occurrence of x with scope f .
3. Any variable which occurs free in f or in t remains free in f (t).
A term a with free variables among x1 , .., xn is denoted by a[x1 , ...x ].
A term without any free variables is called a closed term (or combinator )
Note that a variable may occur both free and bound in a given λ-term. For instance, in
λx.y(λy.xy) the first occurrence of y is free while the second one is bound.
Bound variables establish a correspondence between the argument of a function and positions
within the body of a λ-term where the argument is to be substituted. The actual symbol used
as a bound variable is, of course, irrelevant. This notion of bound variables corresponds closely
to the notion of bound variables in predicate calculus or to parameters appearing in function
declarations in programming languages. Typically free variables only arise in subterms of some
larger (closed) λ-term. The following diagram illustrates the concept of free and bound variables
in a λ-term.
x f ree
z
}|
{
λf. λx. (λz.f xz)x
|
12
though it is due to Schönfinkel and not to Curry
{z
x bound
}
2.6. THE λ-CALCULUS AS A LOGIC OF COMPUTATION
29
The process of substitution of terms for variables is the key computational mechanism in the
λ-calculus.
Definition 2.6.4
Substitution
The term derived from b by substituting every free occurrence of x in b by a is denoted by
b[a/x]. It is defined inductively by the following clauses:
1. x[a/x] ≡ a
13
2. y[a/x] ≡ y where x 6≡ y
3. (λx.t)[a/x] ≡ (λx.t)
4. (λy.t)[a/x] ≡ λy.(t[a/x]) where x 6≡ y and y does not occur free in a or x does not occur
free in t
5. (λy.t)[a/x] ≡ (λz.(t[z/y]))[a/x] where x 6≡ y, z is a new variable different from both x
and y not occurring in either t of a, y does occur free in a and x does occur free in t.
6. f (t)[a/x] ≡ (f [a/x])(t[a/x])
The reason why clause 5 is so complicated is that we need to make sure when substituting a
λ-term for a variable that a free variable does not become bound. This phenomenon is called
capture. Consider the λ-term λx.y which returns y when applied to a λ-term. Suppose we
performed the substitution (λx.y)[w/y]. If w 6≡ x clause 4 would apply and we would get λx.w
as expected. If, however, w ≡ x and clause 5 were not included in the definition we would get
λx.x, a function returning the λ-term it is applied to. The trick of renaming a bound variable
to avoid the capture of free variables is sufficiently useful to deserve its own formal definition.
Definition 2.6.5 α-conversion
A change of bound variables in a λ-term t is the replacement of a subterm of the form λx.b
with x not bound in b by a term of the form λz.b[z/x] where z is a variable that does not at
all occur in b.
A λ-term t is said to be congruent to another λ-term u if u is the result of applying a series
of changes of bound variables to t.
For all practical purposes congruent terms are regarded as being the same. We will often say
“identical” when we should be saying “congruent” if the difference does not matter. A change
of bound variables is often called α-conversion or α-reduction.
We are now ready to define the important concept of reduction which is the key to formalizing
the process of “computing with λ-terms”.
Definition 2.6.6 Reduction between λ-terms is a binary relation −→ which is inductively
defined by the following rules:
Provided z does not occur or bound in b
13
λx.b −→ λz.b[z/x]
≡ stands for identity of λ-terms as syntactical constructs.
(α-reduction)
30
CHAPTER 2. LOGIC AND COMPUTATION
(λx.b)(a) −→ b[a/x]
t −→ u
f (t) −→ f (u)
t −→ u
λx.t −→ λx.u
t −→ u
t(a) −→ u(a)
(β-reduction)
(µ-reduction)
β
14
(ν-reduction)
t −→ u u −→ w
t −→ w
(ρ-reduction)
t −→ t
(ξ-reduction)
(τ -reduction)
β
Example 2.6.7 Reducing a λ-term: (λxyz.x(yz))f g −→ (λyz.f (yz))g −→ (λz.f (gz))
The original λ-term performs function composition
Exercise 2.6.1 Show that (λx1 ..xn .t)u1 ..un is equivalent to simultaneous substitution t[u 1 /x1 ..un /xn ]
(see section 2.4.2)
The only rule with nontrivial computational content is the β-reduction from (λx.b)(a) to b[a/x].
The basic expectation, as in any computational system, is that this computational process
“simplifies” a term producing another term of “equal” value. So far, we have defined the
computational process but do not yet have a notion of equality. Congruence or identity of λterms will not serve since β-reduction does not preserve them. Equality of values will therefore
be defined in terms of the reduction relation, adding a rule for symmetry.
Definition 2.6.8 Equality of λ-terms, written =, is defined by the following rules:
λx.b = λz.b[z/x]
(α-conversion)
(λx.b)(a) = b[a/x]
(β-conversion)
t = u
λx.t = λx.u
(ξ-conversion)
t = u
f (t) = f (u)
(µ-conversion)
t = u
t(a) = u(a)
(ν-conversion)
Provided z does not occur free or bound in b
t = t
(ρ)
t = u
u = t
(σ)
t = u u = w
t = w
(τ )
Equality is often called convertibility. We shall say that two λ-terms are equal if we can prove
that they are equal using the above rules. But how do we establish that two terms t and u are
not equal? Assuming that in λ-calculus there is more than one function which can be defined
we can approach this problem by showing that from t = u we could conclude that any two
λ-terms are equal.
Example 2.6.9 Define T := λu.λv.u and F := λu.λv.v
Assuming T = F we can show that t = u for all λ-terms t and u.
14
Note that capture can occure when using the ξ rule. Indeed it should occur if this rule is to make any
nontrivial statement.
2.6. THE λ-CALCULUS AS A LOGIC OF COMPUTATION
T =F
T (t) = F (t)
T (t)(u) = F (t)(u)
t = F (t)(u)
T (t)(u) = t
F (t)(u) = u
t=u
31
Assumption
ν
ν, β
τ, β
τ
Thus we could “prove” two terms unequal if we can show that assuming their equality leads
to the equation T = F .
So far we have shown how the single steps of a computation in the λ-calculus proceed. Normally
we think of a computation as proceeding until a “result” is obtained. What is the result of
a computation in the λ-calculus? That is, how do we know when we may stop the reduction
process? A straightforward answer to this question is to stop when no more reduction with
computational content is possible. These considerations lead us to single out a special class of
λ-terms which serve as the results of computations in the λ-calculus.
Definition 2.6.10
A term of the form (λx.b)(a) is called a redex and b[a/x] is called its contractum.
Definition 2.6.11
Let t be a λ-term
1. t is in normal form (or normal) if it contains no redices.
2. t is normalizable iff there is some normal s such that t −→ s. s is said to be a normal
from of t.
The appearance of a normal form in a sequence of reductions signals the end of our computation
and the normal form is the resulting value.
Note that the definition of redex refers to the possibility of β-reduction only. Clearly we could
perform α-reductions indefinitely if we wished but this does not lead anywhere. Essentially the
rules which come in addition to β-reduction are nothing but a formal justification for applying
β-reductions to any redex within a term t in order to deduce that t reduces to some term t0 .
Our interest will therefore be focused on β-reductions and we write t −→ s to denote the fact
that s is the result of reducing a single redex in t to its contractum.
2.6.3
Reduction properties of the λ-calculus
The definition of normal forms raises some interesting questions.
1. Does every λ-term have a normal form? Clearly not, as the following example shows
Example 2.6.12 Consider the expression (λx.x(x))(λx.x(x)).
There is exactly one opportunity for β-reduction. If we carry out this reduction we get
exactly the same term as before and have again an opportunity for β-reduction.
32
CHAPTER 2. LOGIC AND COMPUTATION
Terms without normal forms are the analogues of non-terminating programs.
2. If a λ-term has a normal form does any choice of reductions lead to that normal form?
Again the answer is “no”:
Example 2.6.13 Define W := λx.xxx and I := λx.x.
Consider the term F (W W )I with F as in example 2.6.9.
There are two opportunities for β-reduction. Choosing the leftmost one we would get I
immediately. If we would choose to reduce the subterm W W first the result would be
F (W W W )I and applying leftmost reduction we would get I again. Thus there are infinitely
many sequences starting with F (W W )I and ending in I but there is also the infinite sequence
F (W W )I −→ F (W W W )I −→ F (W W W )I −→ . . . which never reaches normal form.
3. How do we know that we will find the normal form if there is one?
This is a fairly subtle question and we will not try to justify the answer formally.
Performing always the leftmost reduction will lead to a normal form if there is one 15 .
Intuitively the reason why this works is that a term which does have a normal form may
have a subterm which does not normalize. However, this subterm may never be needed so we
should apply the “outermost” function to see if a particular subterm is actually needed before
trying to reduce potentially nonterminating subterms. This particular strategy is called normal
order reduction and corresponds to “call-by-name” evaluation. The price we have to pay for
guaranteed termination is a lack of efficiency. Calling by name means that we may have to
normalize the same expression twice if it is doubled by the calling function. If we would know
it to terminate it would be better to reduce it beforehand (“call-by-value”). There is, of course
no way of looking at a generic λ-term and deciding wether a normal form exists or not 16
4. If a λ-term has a normal form, is it unique? The answer to this question follows from the
so-called “Church Rosser”or “confluence” theorem.
Theorem 2.6.14 Church Rosser
For all λ-terms t, u, v if t −→ u and t −→ v then there is a λ-term z such that u −→ z and
v −→ z.
In section 3.2.5 will will sketch a proof of the confluence theorem for the typed λ-calculus.
For the unrestricted λ-calculus a proof is quite complicated. Again we refer to textbooks like
[Bar81, HS86, Ste72].
As an immediate consequence we get
Corollary 2.6.15 Let t, u, v be λ-terms
1. If t has normal forms u and v then u and v are related by α-conversion.
15
16
See a textbook on the λ-calculus (e.g. [Bar81, Ste72]) for a proof.
The halting problem not decidable - see Section 2.6.5
2.6. THE λ-CALCULUS AS A LOGIC OF COMPUTATION
33
2. If u = v (can be proved) then there is a λ-term z such that u −→ z and v −→ z.
(i.e. the calculus defined by Definition 2.6.8 is consistent)
3. If u = v and u is in normal form then v −→ u.
4. If u = v then either u and v have no normal forms at all or the same ones.
5. If u and v are in normal form then they are either α-convertible or not equal.
Thus normal forms are unique which justifies viewing λ-terms as functions.
2.6.4
The expressive power of the λ-calculus
So far we have looked at the λ-calculus as a purely formal system for playing around with terms.
We will now show how to compute with it and that its computational power is equivalent to that
of recursion theory17 . Because of its simplicity there is no doubt that all the constructs from
the λ-calculus are in fact computable. It is, however, this simplicity which makes it awkward
to prove the reverse. Recall that the λ-calculus is a formalism where computation is expressed
via the successive application of reduction rules. Thus expressing computations involves taking
terms that mimic familiar constructs and reducing them to their normal form.
Before investigating recursion theory we will examine a few standard constructs. The pure
λ-calculus provides only one mechanism for making “programs” and “data” interact, namely
application. Quite frequently, however, we would like to have a part of a program execute only
when certain conditions are met. In short, we would like to have a conditional construct. For
that, we need a notion of boolean expressions which can evaluate to “true” or “false”, and a
construct “cond(b; s; t)” that takes a boolean expression b, evaluates it, and depending on the
result either evaluates s or t
Example 2.6.16 Boolean expressions and conditionals
As discussed in Example 2.6.9 the combinators T := λu.λv.u and F := λu.λv.v perform very
well as representatives of “true” and “false”.
Now consider the λ-term b(s)(t) where b evaluates either to T of F . If b evaluates to T then
b(s)(t) = s; otherwise b(s)(t) = t. Thus the conditional is well represented by cond(b; s; t)
:= b(s)(t)
18
Besides structuring the program we need to be able to structure the data as well. The most
basic construct is “pairing” two terms a and b into ha, bii. For this to really qualify as a “data
structure” we need also a means of recovering the original terms a and b from the pair.
Example 2.6.17
17
Pairing and projections
According to Church’s thesis this means that all the effectively computable functions can be expressed in
the λ-calculus.
18
Note that for the sake of readability we have introduced a shorthand notations adopted from programming
languages which does not follow the syntax of the pure λ-calculus.
34
CHAPTER 2. LOGIC AND COMPUTATION
Define ha, bii := λpair.(pair(a))(b)
1 := λp.p(λa.λb.a)
2 := λp.p(λa.λb.b)
Pairing keeps a and b separate as long as the variable pair remains uninstantiated. 1 of ha, bii
instantiates pair with λa.λb.a thus projecting the first component a. 2of ha, bii returns b.
A uniform way to recover both components for usage in another term t is the “spread”
operator spread(pair; a, b.t) := pair(λa.λb.t) which should be read as “In t instantiate
a, b such that pair = ha, bii”
Exercise 2.6.2 Prove that 1of ha, bii = a, 2of ha, bii = b and spread(hha, bii; u, v.t) = t[a, b/u, v]
One way of characterizing the class of computable functions in recursion theory is by µ-recursive
functions19 . For studying computable functions it is sufficient to consider functions over the
set IN of natural numbers.
Definition 2.6.18
rules:
The class of µ-recursive functions is defined inductively by the following
1. All constant functions λx1 x2 ...xk .m where m, k ∈ IN are µ-recursive.
2. The successor function S := λx.x + 1 is µ-recursive.
3. The projections λx1 x2 ...xn .xi are µ-recursive.
4. If f = λx1 ...xk .tf is µ-recursive and the functions gi = λx1 ...xm .tgi where 1 ≤ i ≤ k are
µ-recursive then the function λx1 ...xm .f (g1 (x1 )...(xm ))...(gk (x1 )...(xm )) is µ-recursive.
5. Primitive recursion:
If h = λx1 ...xk xk+1 .th and g = λx1 ...xk−1 .tg with k ≥ 1 are µ-recursive then the function
f which is uniquely defined by
f (0)(x2 )...(xk ) = g(x2 )...(xk ) and f (x + 1)(x2 )...(xk ) = h(x) (f (x)(x2 )...(xk )) (x2 )...(xk )
is µ-recursive.
6. µ-operator:
If f = λx1 ...xk xk+1 .tf is µ-recursive then the function λx1 ...xk .µx [f (x1 )...(xk )(x) = 0] is
µ-recursive. 20
There are many ways to represent natural numbers and operations on them in the λ-calculus.
We shall use a representation due to Church which basically encodes a number n by a λ-term
which takes two arguments and applies the first argument to the second n times. To distinguish
numbers n, m from their representation we will denote the corresponding λ-terms by n̄, m̄.
Definition 2.6.19
Church numerals
For every n ∈ IN the Church numeral n̄ is defined by n̄ := λf.λx. f (f (...f (x))...).
|
19
{z
}
See a textbook like [HR67] for details on recursion theory
A function of 0 variables represents a constant.
If P is a predicate on IN then µx [P (x)] denotes the minimum of the set {x : IN|P (x)}. µx [P (x)] is undefined if
this set is empty.
20
2.6. THE λ-CALCULUS AS A LOGIC OF COMPUTATION
35
In particular, the Church numeral for 0 is λf.λx.x, for 1 it is λf.λx.f (x) and for 2 it is
λf.λx.f (f (x)). A shorthand notation the representation of n is by λf.λx. f (x). We will
need this in proofs.
Exercise 2.6.3 Show that n = m iff and only if n̄ = m̄.
Constant functions (Clause 1 of Definition 2.6.18), Projections (Clause 3) and functions defined
by composition (Clause 4) are now directly representable. We are left with the successor
function, primitive recursion, and µ-recursion.
Now we are ready to do some basic arithmetic within the λ-calculus keeping in mind that the
church numeral for n applied to two arguments applies the first argument n times to the second.
The very first thing we need is the sucessor function.
Example 2.6.20 Successor function
Keeping in mind that the Church numeral for n applied to two arguments applies the first
argument n times to the second, the successor function can be represented by
S := λn.λf.λx. (n(f ))(f (x))
If applied to n̄ the inner term of this operation applies f to f (x) altogether n imes , resulting
¯ 1. This is easy to check as the following calculation shows:
in n +
(λy.λf.λx. (y(f ))(f (x))) (λg.λu.g n(u)))
∗
−→ λf.λx. (λg.λu.g n(u))(f )(f (x))
∗
−→ λf.λx. (λu.f n (u))(f (x))
∗
−→ λf.λx. f n (f (x)) = λf.λx. f n+1 (x)
The other basic arithmetic functions can be encoded fairly easily.
Example 2.6.21 Define plus := λu.λv.λf.λx. (u(f ))(v(f )(x)). Then plus(n̄)(m̄) = n +¯ m
∗
λu.λv.λf.λx. (u(f ))(v(f )(x)) (n̄)(m̄) −→ λf.λx. (n̄(f ))(m̄(f )(x))
∗
∗
−→ λf.λx. (f n )(f m (x)) −→ λf.λx. (f n+m )(x)
Exercise 2.6.4 Show that mult := λu.λv.λf.λx. (u(v(f )))(x) represents multiplication.
Show that exp := λu.λv.λf.λx. ((u(v)(f ))(x)) represents exponentiation.
Show that t0 := λn.(n(λu.F ))(T ) represents a test for zero.
Encoding the predecessor function P with P (0) = 0 and P (s(n)) = n is a rather complicated
exercise but the key for the representation of primitive recursion. We have to build a function
which on input n̄ applies the successor function s to 0̄ n − 1 times. This can be achieved by
causing s to be applied with a delay of one step. The pairing operation is helpful for dooing
so. The actual definition is hard to be justified intuitively but can be proved to be correct.
Exercise 2.6.5 Show that P := λn.2of (n(λf x.hhS, spread(f x; f, x.f (x))ii)(hhλz. 0̄, 0̄ii)) represents the
predecessor function
36
CHAPTER 2. LOGIC AND COMPUTATION
To express primitive recursion, and µ-recursion we need a concept that allows us to define
functions recursively via equations of the form f = t[f ] i.e. equations containg f on both sides.
In the λ-calculus, such an equation does not define a term. It merely states a condition that the
term has to satisfy. Fortunately, there is a way to construct such a term from a given recursive
equation. If we rewrite the above equation into f = T (f ) were T := λx.t[x/f ] then solving the
equation means finding a fixed point of the function T .
Definition 2.6.22 A fixed point combinator is a λ-term R such that for all λ-terms t the
equation R(t) = t( R(t) ) holds.
Example 2.6.23 The most commonly used fixed point combinator is Y := λf.(λx.f (xx))(λx.f (xx)).
The following calculation shows that Y is indeed a fixed point combinator.
Y (t) = (λf.(λx.f (xx))(λx.f (xx)))(t) −→ (λx.t(xx))(λx.t(xx))
−→ t(λx.t(xx))(λx.t(xx)) = t( Y (t) )
It is important to note that Y (t) does not β-reduce to t( Y (t) ). We have merely proven
equality of the two terms.
Exercise 2.6.6 Show that (λx.λy.y(x x y))(λx.λy.y(x x y)) is a fixed point combinator that actually
β-reduces a λ-term to its fixed point.
We can now represent recursively defined numeric operations in the λ-calculus.
Example 2.6.24 An operator for primitive recursion can be defined as
P RK := λg.λh.Y (λf.λx1 ...xk .cond(t0 x1 ; g x2 ...xk ; h (P x1 ) (f (P x1 ) x2 ...xk ) x2 ...xk ))
On input g and h it creates a fixed point of
λf.λx1 ...xk .cond(t0 x1 ; g x2 ...xk ; h (P x1 ) (f (P x1 ) x2 ...xk ) x2 ...xk )
which is exactly the function defined in Clause 5. of Definition 2.6.18
Example 2.6.25 The µ-operator can be represented by a fixed point of unlimited search
starting at x. If f x1 ...xk x = 0 then the search terminates. Otherwise it continues starting
from x + 1. We begin the search at x := 0.
Thus µ := λf.λx1 ...xk .(Y (λM IN.λx.cond(t0 (f x1 ...xk x); x; M IN (x + 1)))(0̄))
is a representation of the µ-operator
2.6.5
Semantic questions
Since the λ-calculus is intended to be about functions there must be some model in which a
term λx.t can be regarded as a mathematical function. It is not difficult to construct a term
model (see [CR36]): each term t denotes the set ktk of terms equal to it21 , and kλx.tk is the
function that maps kuk to kt[u/x]k. But this leads us nowhere. What we are really interested
in is a connection between functions in the λ-calculus and functions in ordinary mathematics.
21
In the sense of Definition 2.6.8
2.7. REFERENCES AND FURTHER READING
37
Simple mathematical models, with λ-terms interpreted as plain functions over some function
space can be ruled out by cardinality considerations. Since λ-terms have to play the double
role of functions and arguments we can construct λ-functions that can be applied to themselves
in a meaningful way.
Example 2.6.26 Consider twice := λf.λx.f (f (x)). Applied to terms f and u, it produces
the twofold application of f to u: twice f u −→ f (f (u)).
It is perfectly legal to apply twice to itself: (twice twice) f u −→ f (f (f (f (u))))
Self-application of functions, however, violates a basic axiom of ordinary set theory. Thus we
cannot expect “natural” models for the λ-calculus as long as we do not put restrictions on the
terms as we will do in the next chapter22 .
Besides the problem of finding a model the general λ-calculus has some severe drawbacks which
make it hardly acceptable as a calculus for reasoning about programs and their properties.
The price we have to pay for its computational power being equivalent to that of recursion
theory is the consideration of partial functions on the one side and undecidability on the other.
The former follows from the fact that not every λ-term has a normal form. A formulation of
the latter is Rice’s Theorem (see e.g.[HR67]) saying that no nontrivial extensional property of
λ-programs is decidable. In particular we cannot decide whether
• the application f (x) of a function f to an argument x terminates (Halting Problem),
• a function f is total,
• a value y is in the range of a function f ,
• for given values x and y f (x) = y is true,
• two functions f and g are equal.
Many more questions occurring in reality are not decidable within a theory as powerful as
the unrestricted λ-calculus. Our search for a calculus for reasoning about programs and their
properties must therefore be directed towards weaker models of computation which provide
more reasoning power and are sufficient for handling all practical problems.
2.7
References and further reading
Introductions to logic for computer scientists can be found in [BM79, Gal86, MW85, Tur84].
The reader interested in mathematical accounts of logical calculi should refer to books like
[Ric78, Sch77, Tak75] where many aspects are worked out in detail.
The beginning chapters of various textbooks on logic and computation [And86, Bib87, GLT89,
Lak76, Pau87] contain many more examples and are also worth looking up.
22
In Section 3.2 we will see that this can be resolved by viewing the definition of twice as a generic name for
a series of functions which in reality are all different because they operate on different spaces.
38
CHAPTER 2. LOGIC AND COMPUTATION
The classical account of natural deduction has been written by Prawitz [Pra65]. It is not
intended for beginners.
Dummet [Dum77] describes the philosophy, inference systems, and semantics of intuitionistic
logic. Further books worth reading are [Cur70, Hey71].
Hindley and Seldin [HS86] wrote a good introduction to the λ-calculus while Barendregt [Bar81]
has written the comprehensive reference. A gentle introduction is also the article of Huet
[Hue86]. The book of Stenlund [Ste72] is also a valuable book in many details.
Chapter 3
Typed Theories
In the previous chapter we have seen that the λ-calculus is both a simple and powerful mathematical model of computation. Because of its expressive power, however, no extensional
property of λ-terms is decidable and therefore it is extremely difficult to automate reasoning
about programs which are defined by unrestricted λ-terms.
Undecidability of program properties, as it turned out, is strongly related to Russels paradox
in early set theory. As the capability of impredicatively forming a set {X|X 6∈ X} leads to
paradoxical situations in set theory1 so the presence of a general fixed point operator Y with
Y (f ) = f (Y (f )) in λ-calculus allows diagonalization arguments proving the undecidability of
extensional properties.
Russel [Rus08] isolated the essence of the paradoxes in the lack of predicativity and restricted
set theory by introducing a type discipline on the objects. Types represent the universes of
mathematical reasoning which do have a meaning in reality. Thus sets like {X|X 6∈ X} cannot
be formed anymore since “∈” relates objects of different types (or cardinality).
In the same way a type discipline can be added to the λ-calculus in order to increase its
reasoning power. In the typed λ-calculus [Chu40] types are both syntactical restrictions and
a representation of natural models for the function spaces where the λ-terms belong to. The
type discipline will help to banish many of the strange constructions in the untyped λ-calculus.
Before we discuss the typed λ-calculus let us approach two questions.
• What is a type or what are the characteristics of a type?
• Which types need to be considered?
To answer the first one, let us consider an example.
Example 3.0.1 Natural numbers
The set IN of natural numbers has elements 0,1,2,3,4. . . and operations between elements
like + - * / etc. An expression like 2*3 uniquely denotes an element of IN and should thus
be considered as a name for it. On the other hand we can reduce 2*3 to the value 6 which is
1
Consider the set S̄ := {X|X 6∈ X} and try to determine whether S̄ is an element of S̄ or it is not.
If we assume S̄ ∈ S̄ then as any other element of S̄ the set S̄ is not contained in itself, i.e. S̄ 6∈ S̄. From
S̄ ∈
6 S̄, however we have to conclude S̄ ∈ S̄ since S̄ consists of all the sets not contained in themselves. Thus
both assumptions lead to contradictions.
39
40
CHAPTER 3. TYPED THEORIES
the normal form of the expression. Therefore we distinguish between canonical members of
the type IN, i.e. names denoting normal forms like 0,1,2,3,4. . . , and noncanonical members,
i.e. expressions which can be reduced.
So rule number one for constructing a type is:
A type is defined by defining its canonical members and operations on the members.
As to the second question, the types we need to consider shall allow interpreting λ-terms as
functions. Therefore we obviously we need a type A→B representing the type of all functions
from some type A into the type B. λ-abstractions λx.b will be the canonical objects of this
type and applications f (a) the noncanonical ones. No other types are necessary for typing
λ-terms. As in the untyped λ-calculus there is no need for concrete types like natural numbers
or booleans.
We will now formalize how types can be assigned to terms and how to formally prove that an
assignment is correct. For this, the untyped λ-calculus will be extended by another abstract
formalism about handling type informations.
Following the course of history we will first present a very simple calculus which incorporates
all the basic principles but later turned out to be too weak in its expressive power. We will
then discuss extensions which have been introduced to strengthen the calculus or make it more
suitable for practical purposes. Some of them will cause slight modifications of definitions given
in the first section but the general principles remain the same.
3.1
Simple Type Theory
There are two ways of imposing a type discipline on λ-terms. The first follows Church’s original
typed λ-calculus [Chu40] and puts types into the terms as in λf A→B .λy A .f A→B (y A ). Essentially
this means modifying Definition 2.6.1 into one for typed λ-terms2 .
The other formulation keeps the untyped λ-calculus in its original form and adds Type Theory
as a separate calculus proving whether a terms belong to a certain type, a statement which is
expressed in the form λf.λy.f (y) ∈ ((A→B)→A)→B
Although these formulations are not exactly the same, their logical consequences are identical
and we will use the names typed λ-calculus and Type Theory interchangeably. We will start
with a formal definition of type- and object-expressions.
Definition 3.1.1
Type-expressions are defined inductively by the following rules
1. Any variable from a predefined set of variables is an atomic type(-expression).
2. If T1 and T2 denote types then also T1 →T2 .
Object-expressions are λ-terms as defined in Definition 2.6.1.
2
From this approach we get the notion of a “typed variable” which we use to express that a variable is a
placeholder for terms of a certain type. in λf A→B .λy A .f A→B (y A ) the variable f is a variable of type A→B.
3.1. SIMPLE TYPE THEORY
41
It should be noted that the same set of variables is used in type-expressions and in objectexpressions. It can be determined from the context whether a variable denotes a type or an
object. For an easier distinction, however, we will use the convention to denote type variables
by capital letters A,B,S,T,. . . while small letters x,y,z,. . . denote object variables.
How do we assign types to λ-terms? Since types shall represent the function spaces where the
function denoted by a λ-term shall belong to there is a simple intuitive scheme we may follow.
Each object variable must belong to some type; a λ-abstraction λx.t must belong to a type
S→T where T is the type of t and S the type of x; an application f (a) has type T if f has
type S→T and the argument a is of type S. Otherwise a term cannot be typed.
Example 3.1.2 The term λf.λx.f(x) has the type (S→T)(→S→T).
Following the above scheme the chain of reasoning is as follows. x must have some type which
we denote by the type-variable S. In order to apply f to x the object-variable f must be of
a function type S→T which causes f(x) to be of type T. Twofold abstraction leads to the
above type structure for the complete term.
Obviously there are λ-terms which cannot be classified by the above scheme.
Example 3.1.3 Consider the expression λx.x(x).
Because of the λ-abstraction it must be a function of some type S→T . Thus, for every s ∈ S
the term s(s) must be in T . Therefore s itself must be in the type S→T . As a consequence,
in order to classify λx.x(x) we must find type-expressions S and T solving the equation
S→T = S. This is not possible since no space in reality is identical to its own function
space.
Based on the above intuitive description how λ-terms should be assigned a type we will now
develop a calculus for formal reasoning about the types of λ-terms. For this we have chosen
the style of a top down sequent calculus as described in section 2.5. To prepare a later implementation and to provide a means to prove metatheorems about properties of typed λ-terms
we will also precise the notion of a formal proof by adopting concepts from proof theory. Let
us explain these by an example proof:
Example 3.1.4 We want to prove that (λx.x + 1)(2) has type IN. A formal proof of this
statement reads:
top
` (λx.x+1)(2)∈IN by intro using IN
top 1
` 2∈IN by IN-intro
top 2
` λx.x+1∈IN→IN by λ-intro
top 2 1
x:IN ` x+1∈IN by +-intro
The proof consists of an initial (top-)goal ` (λx.x+1)(2)∈IN, an inference rule which is
denoted intro using IN and two subgoals named top 1 and top 2 which again have proofs.
Technically, thus, a proof is nothing but a tree whose nodes consist of goals and inference
rules. Obviously the children of a goal are drived from it by applying the rule.
A goal itself is a special form of a sequent. x:IN ` x+1∈IN should be read as “Under the
assumption that x is a variable of type IN we can prove that the conclusion x+1∈IN is true”.
x:IN is called a declaration of a variable x of type IN, x+1∈IN a typing of the expression x+1.
42
CHAPTER 3. TYPED THEORIES
It should be pointed out that the focus of the above proof is checking the type of the expression
(λx.x+1)(2). Provided a sufficiently high expressiveness, however, all the other properties of
a term can be expressed through its type which makes typechecking essentially the same as
theorem proving. This justifies calling Type Theory a proof calculus although it contains only
rules about typehood.
There are two more concepts which did not occur in Example 3.1.4.
Example 3.1.5
top
top 1
We want to show that λx.x is a function which is defined on any type.
A:U ` λx.x ∈ A→A by λ-intro
A:U, x:A ` x∈A by hyp x
In addition to what we had before there is a declaration A:U. We use U as a reserved symbol
standing for a universe of types. A:U declares A to be a type in the universe U and is therefore
often called a type declaration while x:A is an object declaration.
These examples lead to the following definition
Definition 3.1.6
1. A declaration has the form A:U or x:A.
A:U declares A to be a type variable; x:A declares x as object variable of type A.
2. A typing has the form t ∈ T or T ∈ U where t is a λ-term and T is a type expression.
3. A hypotheses list H is a list of declarations x1 :T1 , x2 :T2 ,. . .
4. A goal is a sequent of the form H ` t ∈ T where H is a hypotheses list and t ∈ T a
typing.
5. A hypotheses list is proper iff each variable is declared only once and every type variable
appearing in an object declaration occurs first in a type declaration.
6. An initial goal is a goal H ` t ∈ T where H is a proper hypotheses list containing
declarations of all the type variables in T and no object declarations.
7. A proof is a tree whose nodes are goals and rules such that the goals of the children of a
node are given by the rules.
8. A rule is a mapping from a goal into a list of subgoals.
Rules are intended to be used as rules of inference, i.e. the subgoals they create shall be
sufficient evidence for the original goal. Consistency provided, rules determine the logic the
calculus shall handle. They have to be given explicitely by rule schemes which have to describe
the syntax of the rule and its consequences. As announced, we will describe rules in a top-down
fashion.
Rules for Simple Type Theory come quite naturally. We have to give sufficient conditions for
an expression to form a type expression (denoted by T ∈ U, a λ-abstraction to be a member
of some function type, and an application to be a member of a type.
First of all we may conclude x ∈ A if x:A is a declaration3 . This is the assumption rule from
Section 2.5.3, a rule without any further subgoals. Rules for the formation of types follow
immediately from Definition 3.1.1: “S→T is a type-expression if S and T are”.
3
This includes the case T ∈ U.
3.2. PROPERTIES OF SIMPLE TYPE THEORY
43
Rules dealing with λ-abstraction and application have to express the typing scheme mentioned
above: λx.b belongs to S→T if S is a type expression and, provided x is of type S the term
b can be proven to be of type T by such a rule the canonical forms are introduced. It may be
necessary to rename x to some new y if x already occurs in the assumptions. We express this
by adding the (optional) clause [new y] to the rule. Noncanonical members f (a) of type T
can only be introduced if the type S of the domain of f is provided since in general there is
no way to guess it. We then just have to prove that f is of type S→T and that A is in the
domain type of f since then we are allowed to apply f to a.
In the presentation of rules H, A, H 0 , where H and H 0 stand for lists of hypotheses, is used to
denote that the assumption A occurs in the hypotheses of a goal.
Rule Schemes 3.1.7
H, x:T , H 0 ` x ∈ T
H ` S→T ∈U
· H ` S ∈U
· H ` T ∈U
Simple Type Theory
by hyp x
by → formation
H ` λx.b ∈ S→T by λ-intro [new y]
· H ` S ∈U
· H, y:S ` b[y/x] ∈ T
H ` f (a) ∈ T by intro using S
· H ` f ∈ S→T
· H ` a∈S
Note that in addition to these rules we have the computation rules from the untyped λ-calculus
as meta-rules expressing the semantics of λ-terms.
Exercise 3.1.1
1. Prove X:U ` (λx.λy.x(y))(λz.z) ∈ X→X.
2. Prove A:U, B:U, a:A, f:A→B ` (λeval.λarg.eval(arg))(f)(a) ∈ B.
To establish a relation between Church’s typed λ-calculus [Chu40] and Type Theory we call a
λ-term t to be well-typed (or typed) if t ∈ T can be formally proven for some type T .
3.2
Properties of Simple Type Theory
We will now show that adding a type discipline to the λ-calculus has a lot of advantages since
a couple of good properties of Simple Type Theory can be proven.
First of all, the calculus is sound and properly respects the semantics of the λ-calculus (Section
3.2.1). This appears to be a trivial statement but for a formal theory it is very important to
have a proof for it because there is always a chance for having severe errors in the constructs.
Therefore, as a rule, one should always prove even the most simple facts if one wishes to rely
on them later.
44
CHAPTER 3. TYPED THEORIES
Secondly, it is effectively decidable if a λ-term can be typed and the proof gives us a type-checking
algorithm for Simple Type Theory (Section 3.2.2).
For λ-terms which can be typed will get new answers to the questions stated in Section 2.6.3.
Contrary to the untyped λ-calculus every typed λ-term does have a normal form (Section 3.2.3).
Even more, every reduction sequence of λ-term a terminates (Section 3.2.4), which allows us
to use very efficient reduction strategies. The Church Rosser Theorem, saying that the normal
form of a λ-term is unique, has a much simpler proof than the same theorem for the general
case (Section 3.2.5) since we can make use of the above reduction properties of typed λ-terms.
As a consequence, equality of two typed λ-terms becomes decidable. Thus, altogether, the typed
λ-calculus is a decidable theory of total functions.
Natural models for the typed λ-calculus are easy to find: Interpret a type T as a set D(T ) and
each function type S→T as the set of all functions from D(S) to D(T ). The type constraints
make sure that λx.t can be interpreted as a function in the corresponding set, in the function
call f (a) the argument a is sure to belong to the domain of f . A term can have at most one
type.
3.2.1
Soundness
The following metatheorem shows that the rules of Simple Type Theory do not generate nonsense.
Theorem 3.2.1
Let π be a complete proof for the initial goal H ` t ∈ T . Then
1. t is a closed λ-term.
2. T is a type expression.
3. In all the hypotheses lists of all the nodes of π
• any term in the right hand side of a declaration is either U or a type term,
• all the free variables of the conclusion are defined exactly once.
4. No variable is declared unless it is free in the goal.
5. Every subterm t0 of t receives a type4 such that in each term of the form f (a) the f gets
a type T1 →T2 and a gets the type T1 .
Proof: By simultaneous induction on the shape of proof trees.
2
We can also prove that Simple Type Theory respects the semantics of λ-terms. Semantically
equal terms, i.e. terms having the same normal form, behave identical under the proof calculus.
This again seems to be trivial but is not since the appearance of partial functions in our calculus
could destroy it.
Theorem 3.2.2 If t −→ t0 and t and t0 have the same free variables then H ` t ∈ T is
provable iff H ` t0 ∈ T is provable.
4
By “t receives a type” we mean there is a subgoal of the form H 0 ` t0 ∈ T 0 .
3.2. PROPERTIES OF SIMPLE TYPE THEORY
45
Proof: It suffices to show that if t β-reduces to t0 (in one step) then the proof of H ` t ∈ T
can be modified into one of H ` t0 ∈ T and vice versa. The rest follows then by an induction
on the length of the reduction t −→ t0 . We give a proof by induction on the term structure
of t.
If t is a variable then t0 must be α-convertible to t. By the above condition on free variables
t and t0 must be identical.
Assume we have shown the hypothesis for all λ-terms f, a, f 0 , a0 (of depth n) such that f −→ f 0
and a −→ a0 .
1. If t is λx.a then t0 must be some λx.a0 where a −→ a0 .
Assume H ` t ∈ T is provable. Then the first step in the proof must have been the
λ-intro rule resulting in H ` S ∈ U and H, x : S ` a ∈ T .
By induction hypothesis H, x : S ` a ∈ T can be proven iff H, x : S ` a0 ∈ T has a
proof and applying the same λ-intro rule to H ` t ∈ T gives us a proof for this goal.
The opposite direction can be proven similarly.
2. If t is f (a) and t0 is f 0 (a0 ) (no outer β-reduction) then we may reason similarly to the
above.
3. If t is (λx.b)(a) and t0 is b[a/x] then in any case we must apply the rule intro using S to
H ` t ∈ T and then the λ-intro rule which leads to the following three subgoals:
H ` S ∈ U, H, x : S ` b ∈ T , and H ` a ∈ S
A proof for H, x : S ` b ∈ T can be modified into one for into H ` b[a/x] ∈ T by
replacing any application of the rule “by hyp x” by the proof for H ` a ∈ S.
Conversely, in a proof for H ` b[a/x] ∈ T the subexpression a must receive a type
(Theorem 3.2.1). To modify the proof into one for H, x : S ` b ∈ T any proof for
H 0 ` a ∈ S can simply be replaced by the rule “by hyp x” while all the other proof steps
remain the same.
2
As a consequence we may shorten proofs by reduction knowing that semantically equal λ-terms
behave identically under the calculus of Type Theory.
Corollary 3.2.3
If t and t0 are semantically equal then H ` t ∈ T is provable iff H ` t0 ∈ T is provable.
3.2.2
A type-checking algorithm
As a reversal of Theorem 3.2.1 we will investigate the type-checking problem:
Given an untyped λ-term determine if it is typeable and, if it is, produce it’s principal
typescheme.
The answer to this question is “yes” and is based on an algorithm of Hindley and Milner
[Hin69, Mil78, DM82]5 developed for the language ML which has a very rich polymorphic type
5
See also [Hin83, HS86, CC90]
46
CHAPTER 3. TYPED THEORIES
structure. Its basic strategy is to start with the term t and a type X0 and to try to prove
X0 : U ` t ∈ X0 in the proof system and during refinement also refine X0 and try to prove
constraints of the form Xi = Xj on the type variables.
Example 3.2.4 Try to give a typing to λf.λx.f(x) (c.f. Example 3.1.2).
To prove X0:U ` λf.λx.f(x)∈X0 in our proof system we need to apply the λ-intro rule
twice. This is only possible if X0 is a function type (X1→X2)→X3. Thus, after applying these
rules we have the subgoal:
X1:U, X2:U, X3:U, f:X1, x:X2 ` f(x)∈X3
Here only the rule intro using X2 will lead to a correct proof since X2 is the type of the
argument x. As a result X1 must be X2→X3 in order to correctly type f. Considering these
constraints we get a correct proof for:
X2:U, X3:U ` λf.λx.f(x) ∈ (X2→X3)→(X2→X3)
which gives us the desired typing.
Theorem 3.2.5 Hindley/Milner
It is effectively decidable if a term can be typed or not.
Proof: We present a version of the Hindley/Milner algorithm. Because of the appearance of
but one type constructor it is quite simple and clean:
ALGORITHM:
Start with X0 :U ` t ∈ X0 where X0 is a type variable as an initial goal. Construct a proof
by recursively applying one of the following steps to a goal H ` t ∈ Xi until the proof is
finished or fails.
1. If t is f (a) then use the rule by intro using Xi+1 . Update the environment H accordingly.
2. If t is λx.b then refine Xi to Xi+1 →Xi+2 and use the rule by λ-intro. Update the
environment H and the rest of the proof.
3. If t is a variable x then try to unify6 T and Xi where x:T is a part of H. Update the
environment H and the rest of the proof. If the unification fails then stop with a failure
message.
2
Later we will consider how the Hindley/Milner algorithm generalizes to further type constructs.
Example 3.2.6 We want to type trice ≡ λf.λx.f(f(f(x))). The typing algorithm yields:
top
6
X0:U ` λf.λx.f(f(f(x)))∈X0
by λ-intro
Refine X0 to X1→X2.
Note that updating affects the top goal as well.
Unification is a method to find substitutions for variables such that T 0 = Xi0 after applying the substitution,
i.e. if T = t[x1 , .., xn ] and Xi = s[y1 , .., ym ] look for a unifying set {a1 , .., an , b1 , .., bm } such that t[a1 , .., an ] =
s[b1 , .., bm ]. An algorithm for unification takes terms (as trees) and looks for the first mismatch, replaces variables
by subterms (the ones from the other term), does an occurrence check of these variables in the subterms, and
fails if there are no variables to match.
3.2. PROPERTIES OF SIMPLE TYPE THEORY
top
top
top
top
top
47
1
X1:U, X2:U ` X1∈U by hyp X1
2
X1:U, X2:U, f:X1 ` λx.f(f(f(x)))∈X2 by λ-intro
Refine X2 to X3→X4.
2 1
X1:U, X3:U, X4:U, f:X1, x:X3 ` X3∈U by hyp X3
2 2
X1:U, X3:U, X4:U, f:X1, x:X3 ` f(f(f(x)))∈X4 by intro using X5
2 2 1
X1:U, X3:U, X4:U, X5:U, f:X1, x:X3 ` f∈X5→X4 by hyp f
For this rule to apply X1 must be unified with X5→X4. Updating removes the declaration of X1 and
declares f:X5→X4 in all the nodes of the proof tree. As a result the yet unsolved second subgoal is:
X3:U, X4:U, X5:U, f:X5→X4, x:X3 ` f(f(x))∈X5 by intro using X6
X3:U, X4:U, X5:U, f:X5→X4, x:X3, X6:U ` f∈X6→X5 by hyp f
Unify X6 with X5 and X5 with X4.
top 2 2 2 2
X3:U, X4:U, f:X4→X4, x:X3 ` f(x)∈X4 by intro using X7
top 2 2 2 2 1
X3:U, X4:U ,X7:U, f:X4→X4, x:X3 ` f∈X7→X4 by hyp f
Unify X7 with X4.
top 2 2 2 2 2
X3:U, X4:U, f:X4→X4, x:X3 ` x∈X4 by hyp x
Unify X4 with X3.
top 2 2 2
top 2 2 2 1
Thus just one type variable remains. Writing A instead of X3 we have proven:
top
A:U ` λf.λx.f(f(f(x)))∈ (A→A)→(A→A)
Note that a typing of the function trice restricts the possibilities for self-application. Although
it is still perfectly legal to apply trice to itself a typing reveals that in trice(trice) both
instances have a different typing. While trice as argument has type (A→A)→(A→A) the type
of trice as function is ((A→A)→(A→A)) → ((A→A)→(A→A)) and thus of much higher
level.
Exercise 3.2.1
1. Give a typing for λt.λy.t(y)(y).
2. Give a typing for f(a) with f ≡ λx.x(x(x(y))), a ≡ λz.(g(z))(z).
3. Show that the principal type-scheme of the Church numerals (Section 2.6.4) representing a number n by λf.λx.fn(x) is (X→X)→(X→X).
4. How does the typechecking algorithm behave on λx.x(x)?
5. Show that the fixed point operator Y ≡ λf.(λx.f(x(x)))(λx.f(x(x))) cannot be typed.
3.2.3
Weak Normalization
In this section we want to show that for every well-typed λ-term there actually is a terminating
term-reduction sequence. We know from Section 2.6.3 that leftmost reduction will always lead
to a normal form if there is one. But there is a much more efficient reduction strategy which
can also be proven to terminate7 . It follows from taking a look at the complexity of the type
structure of an expression. For instance, a type-structure (A→B)→(C→D) has two levels of
function space formation. Another way of speaking is to say “(A→B)→(C→D) has depth 2”.
If we try to reduce the depth of the type structure of an expression then the reduction should
terminate. This, of course, requires some typing of an expression.
7
Although the next section proves that all reduction sequences terminate this result is quite valuable. It
gives us a very effective way to compute λ-terms which also terminates for classes of λ-terms which are not
strongly normalizable. See Section 4.2.1.
48
CHAPTER 3. TYPED THEORIES
Definition 3.2.7
The depth d(T ) of a type T is inductively defined by
1. d(A) = 0, if A is atomic,
2. d(A→B) = 1 + max{d(A), d(B)}
The depth of a redex (λx.t)(a) is the depth of the type of λx.t.
The depth of a λ-term t is the supremum of the depth of the redices it contains. (The depth
of a term in normal form is 0.)
A first idea would be to reduce the maxdepth-redex first. This strategy however may not always
succeed because reduction may blow up the number of maxdepth-redices if they are arguments
of a function application.
Example 3.2.8 Consider the redex trice(trice(λx.x)) with trice ≡ λf.λx.f(f(f(x)))
from Example 3.2.6. The type of trice is (A→A)→(A→A) thus both trice(trice(λx.x))
and trice(λx.x) are redices of depth 2. Reducing the outer redex trice(trice(λx.x)) first
yields λx. (trice (λx.x)) ( (trice (λx.x)) ( (trice(λx.x)) (x)) ) which contains
one redex of depth 2 more than we had before. Thus combinatorial arguments alone would
not guarantee termination of this reduction.
If we reduce the rightmost redex with maximal depth first then this effect cannot happen:
Lemma 3.2.9 If we reduce the rightmost maxdepth redex r in a term t which is typed then
the number of maxdepth redices in t decreases.
Proof: When we perform rightmost maxdepth β-reduction then the following things happen:
• The redices outside r remain
• The redices strictly inside r remain unchanged but sometimes are proliferated when reducing r. Their depth, however, is less than the depth of r since they appear as arguments
in the redex rigth of r.
• The redex r itself is destroyed.
Thus one maxdepth-redex will disappear with a chance of increasing the redices of lesser
degree.
2
Example 3.2.10 Again consider trice(trice(λx.x)) with trice ≡ λf.λx.f(f(f(x))).
Reducing the rightmost max-depth redex trice(λx.x) first yields
trice (λx.(λx.x)((λx.x)((λx.x)(x))), i.e. a term which contains only one redex of
depth 2. Although the overall number of redices has grown all the new redices are of lesser
degree while the number of maxdepth-redices has been reduced. Repeating this process will
stepwisely eliminate all redices of depth 2 then all of depth 2 until there are no more redices.
Theorem 3.2.11 For any typed λ-term t ∈ T we can find a number n such that a sequence
of rightmost maxdepth reductions terminates within n steps.
3.2. PROPERTIES OF SIMPLE TYPE THEORY
49
Proof: Show by double induction over d and m using Lemma 3.2.9:
For all d, m ∈ IN: If t has at most m redices of depth d and none of greater depth then there
∗
is some n ∈ IN and some t0 which is normal such that t −→ t0 in n steps.
2
Exercise 3.2.2 Complete the proof of Theorem 3.2.11
Corollary 3.2.12
3.2.4
Every typed λ-term has a normal form.
Strong Normalization
By Theorem 3.2.11 we have shown that there is a terminating reduction sequence for every
term and that there is a strategy to find it. But in the simple typed λ-calculus the typed terms
even have a much stronger property, namely that every reduction eventually terminates. This
property is called strong normalization.
Definition 3.2.13
A term t is strongly normalizable (SN) if every reduction sequence of t is finite.
We will now show that all typed λ-terms are strongly normalizable. For simple Type Theory,
there are proof theoretic techniques which are much simpler than the method we will present
here8 . The advantage of the so-called TAIT computability method [Tai67] (with technical improvements by Girard [Gir72]), however, is that it generalizes to higher order and polymorphic
λ-calculus and other constructs will appear later in our theory. The proof therefore considers
situations which may appear trivial in the current context but become important later.
Essentially, it is an inductive proof which proceeds in two steps. In the first step we will
show that all typed λ-terms are computable, a condition that is even stronger than strong
normalization and yields more information as induction hypothesis. The second step then is to
show that all computable terms are strongly normalizable.
Definition 3.2.14 Computable λ-terms are defined inductively by the following rules:
1. If t ∈ A for some atomic type A and t is SN then t is computable.
2. If t ∈ (S→T ) and t(s) is computable for every computable s ∈ S then t is computable.
Definition 3.2.15
A λ-term is neutral if it is not of the form λx.t
Both notions can easily be generalized to other type theoretic constructs.
Lemma 3.2.16 For all types T and all λ-terms t, t0 of type T
1. If t is computable then t is strongly normalizable.
2. If t is computable and (t −→ t0 ) then t0 is computable.
3. If t is neutral and every β-reduction of a redex in t leads to some computable term t 0 then
t is computable.
8
Using combinatorial arguments as for the case of weak normalization
50
CHAPTER 3. TYPED THEORIES
4. If t is neutral and normal then t is computable
Proof: Clause 4. follows immediately from Clause 3..
We prove the other clauses by simultaneous induction on the type structure of t.
Atomic types: By definition 3.2.14 a term is computable iff it is SN.
1. is a tautology.
2. If t is SN and (t −→ t0 ) then all the reduction sequences of t0 are subsequences of reduction
sequences of t. Thus they must terminate and t0 is SN.
3. By assumption any reduction sequence of t passes through some computable term t0 . Since
s is SN the reduction sequence terminates. Thus t is SN.
Arrow types: By definition 3.2.14 a term is computable iff all its applications to computable
terms are computable. Assume 1., 2., 3. hold for all terms of type T1 or T2 :
1. Let t ∈ T1 →T2 be computable and x be a variable of type T1 . Since x is neutral
and in normal form it is computable by the induction hypothesis for Clause 3.. By
definition t(x) is computable and SN by the induction hypothesis for Clause 1.. Let
t −→ t0 −→ t00 −→ . . . be a reduction sequence for t. The we can construct a reduction
sequence t(x) −→ t0 (x) −→ t00 (x) −→ . . . for t(x) which must terminate in finitely many
steps. Since x is already in normal form the original reduction sequence terminates as
well and t is SN.
2. Let t be computable and (t −→ t0 ) and s of type T1 be computable. Then t(s) is computable and (t(s) −→ t0 (s)). By the induction hypothesis for Clause 2. t0 (s) is computable
and thus t0 as well.
3. Let t be neutral, every β-reduction of a redex in t lead to some computable term t0 , and s
of type T1 be computable. Since, by the induction hypothesis for Clause 1. s is SN we can
prove by another induction on the number of reduction steps of s that every β-reduction
of a redex in t(s) leads to some computable term. There are two ways to β-reduce t(s):
β
• If (t(s) −→ t0 (s)) then t0 (s) is computable because t0 is.
β
• If (t(s) −→ t(s0 )) then s0 is computable by the induction hypothesis for Clause 2.
and the number of reduction steps of s0 is smaller than that of s. Thus by induction
hypothesis for s0 every β-reduction of a redex in t(s0 ) leads to some computable term
and thus t(s0 ) (a neutral term) is computable by the induction hypothesis for Clause
3..
• Since t is neutral t(s) cannot itself be a redex.
By the induction hypothesis for Clause 3. t(s) is computable. By definition t is computable.
2
The technique of choosing variables of some type T allows a proper treatment of all types
uniformly. The variable represents all the members of T and the case that a variable of type T
occurs in a reduction sequence although T has no members which could be instantiated for it.
Lemma 3.2.17
computable.
If for all computable terms b the term t[b/x] is computable then λx.t is
3.2. PROPERTIES OF SIMPLE TYPE THEORY
51
Proof: By Definition 3.2.14 we have to show that (λx.t)(b) is computable for any computable
b.
By Lemma 3.2.16 t = t[x/x] and b are computable and SN. We may therefore reason about
the number of reduction steps of t and b and try to apply Clause 3. of Lemma 3.2.16. There
are three ways to β-reduce (λx.t)(b).
β
• If (λx.t)(b) −→ t[b/x] then t[b/x] is computable by assumption. (This also covers the
base case of our induction.)
β
β
• If (λx.t)(b) −→ (λx.t0 )(b) then t −→ t0 and thus t0 is computable. By induction hypothesis (λx.t0 )(b) is computable.
β
β
• If (λx.t)(b) −→ (λx.t)(b0 ) then b −→ b0 and thus b0 is computable. By induction hypothesis (λx.t)(b0 ) is computable.
In any case (λx.a[x])(b) β-reduces to computable terms only. Since (λx.a[x])(b) is neutral it
is computable. Thus λx.t is computable.
2
The next lemma prepares the main theorem by proving a stronger result which is better fit for
induction.
Lemma 3.2.18 Let t be an arbitrary typed λ-term all of whose free variables are among
x1 , ...xn and let bi be computable terms of the same type as xi . Then t[b1 /x1 ...bn /xn ] is
computable.
Proof: By induction on the type structure of t[x1 , ...xn ].
Base case: If t is a variable xi then t[b1 /x1 ...bn /xn ] = bi is computable.
Assume we have shown the claim for u, f and a.
• If t = λx.u then t[b1 /x1 ...bn /xn ] = λx.u[b1 /x1 , ...bn /xn ] and by Lemma 3.2.17 we have to
show that u[b1 /x1 , ...bn /xn , b/x] is computable for all computable terms b. This, however,
follows by the induction hypothesis.
• If t = f (a) then t[b1 /x1 ...bn /xn ] = f [b1 /x1 ...bn /xn ](a[b1 /x1 ...bn /xn ]). by induction hypothesis f [b1 /x1 ...bn /xn ] and a[b1 /x1 ...bn /xn are computable and by definition of computability
of f [b1 /x1 ...bn /xn ] the term t[b1 /x1 ...bn /xn ] is computable.
2
Theorem 3.2.19
All typed λ-terms are computable.
Proof: Using Lemma 3.2.18 with bi := xi and Clause 3. of Lemma 3.2.16
Theorem 3.2.20
2
All typed λ-terms are strongly normalizable.
Proof: By Theorem 3.2.19 and Clause 1. of Lemma 3.2.16
2
As a consequence we can apply an even more effective strategy which we could hardly justify
to terminate if we had not strong normalization.
Exercise 3.2.3 Show how trice(trice(λx.x)) with trice ≡ λf.λx.f(f(f(x))) reduces under
Leftmost reduction (“call by name”), Rightmost-maxdepth reduction, and under Rightmost reduction
(“call by value”).
52
CHAPTER 3. TYPED THEORIES
3.2.5
Confluence: the Church-Rosser Theorem
From the untyped λ-calculus we know that different reduction sequences always lead to the
same normal form (Theorem 2.6.14) but because of the chance of nontermination the proofs
of the general Church-Rosser Theorem are very complicated. In this section we will prove a
special version, the confluence theorem, of this theorem for the typed λ-calculus. Since we know
that every reduction sequence terminates the proof will be much easier.
r
Definition 3.2.21 Let −→ be a reduction relation on terms, x and y be terms.
∗
1. x −→ y iff y results from x within finitely many reduction steps.
+
∗
2. x −→ y iff x −→ y but at least one reduction step has taken place.
+
3. ∆+ (x) = {y|x −→ y}.
Note that a reduction relation is not necessarily transitive.
r
Definition 3.2.22 Let −→ be a reduction relation on terms, x and y be terms.
∗
∗
1. x ↑ y iff ∃z. z −→ y ∧ z −→ x.
∗
∗
2. x ↓ y iff ∃z. y −→ z ∧ x −→ z.
r
3. −→ is confluent iff for all terms x, y: x ↑ y ⇒ x ↓ y
r
r
r
4. −→ is locally confluent iff for all terms x, y, z: (z −→ y ∧ z −→ x) ⇒ x ↓ y
Confluence means that the following reduction diagram commutes while local confluence guarantees x ↓ y only if x and y are
derived from the same term within one step.
t
x↑y
?
@
y
@
x↓y
@
?
@
R
@x
@
? @R
@z ?
Under the assumption of strong normalization confluence and local confluence is just the same.
Lemma 3.2.23 Let −→ be strongly normalizable and locally confluent. Then −→ is a
confluent reduction relation.
Proof:
∗
∗
Let x −→ xn and x −→ ym within n resp.
m steps. Show xn ↓ ym by induction on wellfounded trees of all reductions of a term following the so-called well-founded induction principle:
“If (∀y ∈ ∆+ (x). P (y)) ⇒ P (x) is true then
P (x) holds for all terms x.”
By local confluence x1 ↓ y1 (to some z),
Since xn , z ∈ ∆+ (x1 ): xn ↓ z to w (induction),
Since ym , w ∈ ∆+ (y1 ): ym ↓ w to y (induction).
x
@
R
@y1
@
@
R
@z @
x
1
@
@
@
R
@ym
x
n
@
R
@w
@
@
@
@
@
R
@y
2
53
3.2. PROPERTIES OF SIMPLE TYPE THEORY
β
In typed λ-calculus −→ is locally confluent.
Lemma 3.2.24
Proof: Analyze all possible cases by considering
the following diagram:
-
(λx.b)(a)
?
(λx.b)(a0 )
b[a/x]
2
?
-
b[a0 /x]
-
b0 [a0 /x]
?
(λx.b0 )(a)
? ?
(λx.b0 )(a0 )
?
Theorem 3.2.25 [Church-Rosser Theorem for typed λ-calculus]
In typed λ-calculus −→ is confluent.
Corollary 3.2.26
Any typed λ-term has a unique normal form.
Proof: Using weak normalization (Theorem 3.2.12) and the Church Rosser Property
2
Corollary 3.2.27 Denotational equality of typed λ-terms is decidable.
Proof: Let t and s be arbitrary λ-terms. In the first step decide if both can be typed (Theorem
3.2.5). Then compute the unique normal forms and check if they are α-convertible (Corollary
2.6.15 2.).
2
3.2.6
The strength of the calculus
A close look at the rules of Simple Type Theory and the implicational fragment of the sequent
calculus for logic (Section 2.5.4) reveals intriguing analogies which were first exposed by Curry
and Feys [CFC58], Tait [Tai67], and Howard [How80]:
The rule for λ-abstraction saying how to build from a variable x of type S and a term b of type
T a new term λx.b ∈ S→T is quite similar to the ⇒ -introduction rule:
H ` λx.b ∈ S→T
by λ-intro [new y]
·H ` S∈ U
Γ ` S ⇒T
by ⇒ -intro
· Γ, S ` T
· H, y:S ` b[y/x] ∈ T
Also the rule for applying a function f ∈ S→T to an argument a ∈ S to get a value f (a) ∈ T
has some similarity to modus ponens9 .
H ` f (a) ∈ T
by intro using S
Γ ` T
by ⇒ -elim
· H ` f ∈ S→T
· Γ ` S ⇒T
· H ` a∈S
·Γ ` S
In both cases the only difference is that the rules of Simple Type Theory contain more information. If, however, instead of looking only at the truth of a proposition we consider the set
9
Recall that the ⇒ -elimination given in Section 2.5.4 rule is modus ponens written as a rule operating on
the hypotheses.
54
CHAPTER 3. TYPED THEORIES
of all its proofs the similarity becomes even more striking. If assuming a proof x of S we have
a proof b for T then λx.b is a proof of the implication S ⇒ T , and a proof f for S ⇒ T and a
proof a for S can be combined (f (a)) into one for T . Thus, there is an isomorphism between
Simple Type Theory and the implicational fragment of logic10 if we translate according to the
following vocabulary:
Variable of type S
Assumption S
Term of type S (with free variables of type Ai ) Proof of S (from assumptions Ai )
Rule for λ-abstraction
⇒ introduction
Rule for application
⇒ elimination
This isomorphism, which has become known as the Curry-Howard Isomorphism, indicates that
Type Theory is not limited to reasoning about datatypes and programs but can simulate logic
as well. It therefore is a promising approach towards a unified formalism for both mathematical
reasoning and programming. As for the simple version, however, there is a price we have to
pay for all the good properties:
Example 3.2.28 In Exercise 3.2.1 we have seen that the principal type-scheme of the Church
¯ ≡ (X→X)→(X→X). Recalling that the Church numeral for n applied to two
numerals is IN
arguments applies the first argument n times to the second (c.f. Section 2.6.4) the following
operator PR represents a simplified primitive recursion:
PR ≡ λh.λg.λn.n(h)(g)
¯ and h a member of IN→
¯ IN.
¯ There is, however, no way
where n and g have to be of type IN
to properly type PR since and n-fold application of h to g, as PR shall do, requires n to be of
¯ IN)→(
¯
¯ IN)
¯ as well. This leads to a recursive equation for the type IN
¯ which has
type (IN→
IN→
¯ = (IN→
¯ IN)→(
¯
¯ IN).
¯
no solution: IN
IN→
The key to the primitive recursion in PR is an unrestricted polymorphic use of n as a member
of (X→X)→(X→X) for different instantiations of X at the same time which is not possible
in Simple Type Theory. The function trice from Exercise 3.2.6 gave us a similar problem. It
is legal to apply trice to itself only if we give it two different typings at the same time and
thus consider trice nothing but a generic name for a class of functions.
Thus there are computable functions which cannot be expressed in Simple Type Theory. To be
more specific the strength of Simple Type Theory is way below the primitive recursive functions,
as we just have seen11 . Such a weakness forbids the consideration of simply typed λ-terms as
a serious programming language.
However, types are useful in programming because they provide partial specifications and checking the type of a term can thus be seen as partial verification. Thus we should look for extensions
of Simple Type Theory to systems with the same global properties but with greater expressive
power.
10
i.e. the part of logic which is based on implication only
One might also deduce this from the fact that the complexity of the normalization procedure is “only”
superexponential which means that only algorithms with a comparably small complexity can be expressed.
11
3.3. THE MATHEMATICS OF U∈U
3.3
55
The Mathematics of U∈U
In the late sixties Per Martin-Löf [ML70] developed an extension of Simple Type Theory based
on intuitionistic second order logic which is also called the Theory of Species [Ste72]. The
resulting calculus is still very simple but extremely powerful. Although it turned out to contain
some other severe problem it gave rise to the development of many successful calculi which are
based on its ideas12 .
3.3.1
Dependent function types
Obviously, the simple function type constructor does not catch all of the meaning of λ-terms
which do have a function as counterpart in reality. We already saw that even simple primitive
recursion cannot be expressed in a simple type-scheme. Let us investigate a few more examples.
Example 3.3.1 The function eval ≡ λf.λx.f(x) expresses a general interpreter for a functional programming language. Obviously we need to be able to express such a function.
According to the Hindley/Milner Theorem the principal typescheme of this function is
(A→B)→(A→B) and everything appears to work. What we see here, however, is again a
polymorphic typing of a function, i.e. the type is determined up to the instantiation of type
variables. Thus, as long as we have only simple types, we can apply eval only to functions
on some fixed space S→T and to others we must apply a different evaluation function. This
is obviously not what we intend to have.
Besides polymorphic functions there is another kind of functions that cause problems:
Example 3.3.2 Consider f ≡ λx.if property(x) then λy.b else b.
Depending on the properties of an input x the range of f is either a function space S→T or
simply the type T of b. Although we can immediately give an interpretation to f it cannot
be typed even if we would allow polymorphic typing.
Functions of that kind often occur when strategic behaviour, for instance in search problems,
shall be programmed. Depending on the value of x the result can be determined immediately
or further input is required before an answer can be given.
In the above example we have a dependency between the output type and the value of the input.
In order to catch this notion we will introduce a new type concept that expresses dependencies
and denote by x:S→T a function space where the type T of the result b of a function λx.b
depends on the value of the argument x ∈ S. This modification has various consequences
because we have to allow proofs for sequents of the form
A:U ` λa.f (a)∈ x:A→T .
Considering the meaning of dependency, applying an introduction rule will result in
A:U, a:A ` f (a)∈ T [a/x].
12
Girard’s Systems F and Fω [Gir71, Gir86, GLT89] and Coquand’s Calculus of constructions [CH85, CH88]
and, of course, Martin-Löf’s predicative Type Theory [ML73, ML82, ML84].
56
CHAPTER 3. TYPED THEORIES
For that we must be able to express the type T as a function depending on a parameter x, i.e.
T [a/x] is the result of reducing B(a) for some B ∈ A→ U. But what shall be the meaning of A→
U? If we want to avoid unnecessary complications of the theory it must be a type expression.
As a consequence, U itself must be a type expression, i.e. the collection of all types is a type
again13 . If we would modify Definition 3.1.1 accordingly we would get
1. U is a type expression.
2. If T is a variable from a predefined set of variables then T is a type-expression.
3. If T1 and T2 denote types and x is a variable then x:S→T is a type-expression.
However, dependencies cannot be expressed in such a simple way since we have not yet solved
the problem of how to make sure that also the expression T (a) is a type-expression for T ∈ A→
U and a ∈ A. Apparently the definition of type-expressions would become quite complicated if
we would try to find a proper syntactical restriction.
The only real answer to this question seems to abandon the syntactical separation of objectand type-expressions and rule out semantical nonsense by the proof calculus. Consequently
the notions of objects and types are mixed, becoming the same concept. We will be allowed
to formulate terms which have no meaning but are not rejected by a syntax-check. Only the
failure of a formal proof where these terms are involved indicates that they are not well-formed.
As a result we get the following new definition of expressions without a distinction between
types and objects.
Definition 3.3.3
An expression is
1. a variable from a predefined set of variables not including U,
2. an application f (a), where f and a are expressions,
3. an abstraction λx.b where b is an expression and x a variable,
4. x:S→T , where S, T are expressions and x is a variable,
5. U.
Independent types S→T then would be just a shorthand notation for the type x : S→T with
T being independent of x. Still, we use small and capital letters to make distinctions between
types and objects but this is just a convention which does not affect the theory itself.
The rules for the theory of dependent types are only a slight modification of those of Simple
Type Theory. Dependencies must be incorporated in the range type of a function space and
the rule for introducing application has now to include the full type x:S→T 14 because there is
no general way to automatically discover the dependencies of T from x ∈ S. Only one axiom
U∈U needs to be added in order to express that the collection of types is itself a type.
The result is a very clean theory which is quite similar to the untyped λ-calculus whose computation rules are still used besides the calculus for the types.
13
This has nothing to do with Russel’s paradox - we are just considering one specific class which becomes a
member of itself.
14
It has to be given in canonical form since S appears explicitely in the second subgoal.
57
3.3. THE MATHEMATICS OF U∈U
Rule Schemes 3.3.4
H, x:T , H 0 ` x ∈
H ` U∈U
Theory of Dependent Types15
by hyp x
by U-formation
H ` x:S→T ∈U by → formation
· H ` S ∈U
· H, x:S ` T ∈U
H ` λz.b ∈ x:S→T by λ-intro [new y]
· H ` S ∈U
· H, y:S ` b[y/z] ∈ T [y/x]
H ` f (a) ∈ T [a/x] by intro using x:S→T
· H ` f ∈ x:S→T
· H ` a∈S
We need one more modification of Simple Type Theory in order to rule out semantical nonsense.
So far constructs like λx.U are not prevented from appearing on the left hand side of legal proof
goals. If we forbid initial goals (c.f. Definition 3.1.6) to have any assumption then all constructs
are checked by the proof rules before they appear in an assumption and we are on the safe side.
Definition 3.3.5
An initial goal has the form “ ` t ∈ T ” where t and T are expressions.
Exercise 3.3.1
1. Show why the fixed point operator Y ≡ λf.(λx.f(x(x)))(λx.f(x(x))) cannot be typed in the
theory of dependent types.
2. Prove ` λA.λx.x ∈ A:U → (A→A).
16
3. Prove ` λA.λB.λg.λb.λx.b(g(x))
∈ A:U → B:(A→U) → g:(A→A) → b:(y:A→B(y)) → x:A→B(g(x))
4. Prove Strong Normalization for the theory of dependent types.
5. Does the Hendley-Milner result (Theorem 3.2.5) hold true for a theory with dependent types? 17
3.3.2
Expressiveness of the theory of dependent types
Although the theory of dependent types is still a very simple theory it is much more powerful
than Simple Type Theory because many explicit constructs can be expressed in it18 .
Let us begin with further exploiting the Curry-Howard Isomorphism we mentioned in Section
3.2.6. We already know how to express the implicational part of logics. With the dependent
15
In addition to these rules we still have the computation rules from the untyped λ-calculus as meta-rules
expressing the semantics of λ-terms.
16
i.e. λx.x is the identity on any type A.
17
Probably it is classically solvable but not by an algorithm.
18
In a practical implementation this would mean to formally prove properties and rules of these constructs
and then, for the sake of efficiency, implement them directly. The outer appearance would be a large formal
but the kernel would be very small and metatheorems would be much easier to prove. The advantage is that
everything represented within the theory does not need to be proven consistent anymore and we only have to
worry about faithfulness.
58
CHAPTER 3. TYPED THEORIES
types we find another correspondence. The rules for x:S→T strongly resemble those of ∀x.T
if we assume the universe of x in the latter to be S (denoted by ∀x:S.T . Now λ-abstraction
corresponds to ∀-introduction and application to ∀-elimination (see Section 2.5.4)19 .
Exercise 3.3.2 Explain the correspondence between dependent functions and universal quantifiers
Since the Theory of dependent types is a higher order theory the Curry-Howard Isomorphism
implication and universal quantification allow us to express all of logics as the following examples will show. Note that a construct simulates another if the proof rules or the logical
consequences are the same. Recall that ∀x : S.T and S ⇒ T are simulated by x : S→T and
S→T .
Example 3.3.6 Conjunction: A ∧ B is expressed by ∀P:U.(A ⇒ (B ⇒ P)) ⇒ P which may
be read as “Any proposition is true if we can prove it from B while assuming A”.
According to the sorted versions of the rules in Section 2.5.4 a proof for the right hand term
would read as follows:
top
top
top
top
top
top
top
1
1
1
1
1
1
1
1
1
1
1
` ∀P:U.(A ⇒ (B ⇒ P)) ⇒ P by ∀-intro
P:U ` (A ⇒ (B ⇒ P)) ⇒ P by ⇒ -intro
P:U, A ⇒ (B ⇒ P) ` P by ⇒ -elim
1
P:U, A ⇒ (B ⇒ P) ` A
2
P:U, B ⇒ P ` P by ⇒ -elim
2 1
P:U, B ⇒ P ` B
2 2
P:U, P ` P by assumption
The only remaining subgoals are top 1 1 1 and top 1 1 2 1. Thus, in order to prove
∀P:U.(A ⇒ (B ⇒ P)) ⇒ P it is necessary and sufficient to prove A and B which is exactly
the same as the ∧ -introduction rule. A slight modification of the above proof shows that
A ∧ B implies ∀P:U.(A ⇒ (B ⇒ P)) ⇒ P. The opposite direction can be proven accordingly.
Example 3.3.7 Disjunction: A ∨ B is simulated by ∀P:U.((A ⇒ P) ⇒ (B ⇒ P)) ⇒ P.
This expresses the elimination rule for disjunction: “A proposition follows from A ∨ B iff it
follows both from A and from B”.
As before negation ¬A is simulated by A ⇒ Λ where Λ stands for falsehood. There are two
interpretations of falsehood, a classical one and an intuitionistic one. We give the intuitionistic
version.
Example 3.3.8 Intuitionistic Falsehood is expressed by ∀P:U.P which formalizes the statement “everything is true”. If this statement would have a proof then we could prove every
proposition to be true. This corresponds to the intuitionistic Λ-elimination rule.
Example 3.3.9 Existential Quantification: ∃x : S.A is expressed by its elimination rule
“A proposition follows from ∃x : S.A if it follows from arbitrary A[x]”:
∀P:U.(∀x:S.(A ⇒ P)) ⇒ P
19
Actually, the dependent type construct is more general since it also catches the notion of “sorted logics”,
i.e. logics, where variables can be assigned different universes.
3.3. THE MATHEMATICS OF U∈U
59
We can even simulate equality of two terms:
Example 3.3.10 Equality: Two terms x and y of type A are equal if they cannot be
distinguished by any proposition: ∀P:A→U.(P(x) ⇔ P(y)).
Thus the theory of dependent types is strong enough to represent all the concepts of predicate
logic.
Exercise 3.3.3 Show that the above simulations do in fact represent Conjunction, Disjunction,
Falsehood, Existential Quantification, and Equality.
Furthermore, we can assign types to all the programming concepts discussed in 2.6.4:
Example 3.3.11 Boolean expressions and conditionals:
In Example 2.6.16 we already discussed that T ≡ λX.λu.λv.u and F ≡ λX.λu.λv.v can be
used as representatives of “true” and “false”. The corresponding type would be
Bool ≡X:U→X→X→X.
Why the additional type variable X is needed can be seen from the conditional, formerly
simply cond(b;s;t) ≡ b(s)(t). The boolean term b must accept terms s and t of arbitrary
type X and therefore must be passed X as additional parameter in order to be typed uniquely.
Thus the conditional cond is expressed by
cond ≡ λX.λb.λs.λt.b(X)(s)(t) and gets the type X:U→Bool→X→X→X.
Example 3.3.12 A unit type, 1 with just one element can be expressed by X:U→X→X. This
corresponds to the logical statement that every proposition implies itself (∀P:U.P ⇒ P) which
is always true.
Example 3.3.13 Pairing and projections: (c.f. Example 2.6.17)
Pairs have been expressed by ha, bii ≡ λpair.(pair(a))(b). Again, a unique typing requires
an additional type variable determining the range type of pair:
ha, bii ≡ λX.λpair.(pair(a))(b). The corresponding type is the product of the types A and
B with a ∈ A, b ∈ B and is expressed by: A#B ≡ X:U→((A→B→X)→X).
Example 3.3.14 Natural Numbers had been represented by Church Numerals with a number n expressed by λf.λx.fn (x). If we add an additional type variable we can avoid the
problems mentioned in Section 3.2.6. As a consequence, the type of Church numerals becomes
¯ ≡ X:U→((X→X)→(X→X)).
IN
¯ we get n(IN)
¯ ∈ (IN→
¯ IN)→(
¯
¯ IN)
¯ and primitive recursion can now be
Thus for n ∈ IN
IN→
¯
expressed as a typeable term PR ≡ λh.λg.λn.n(IN)(h)(g).
Having understood how to define a type of natural numbers we can go even further and try to
develop a technique for representing arbitrary recursive datatypes like lists and trees.
60
CHAPTER 3. TYPED THEORIES
Example 3.3.15 Finite lists over elements of A can be defined by inserting A into the type
we used for Church Numerals: A list ≡ X:U→((A→X→X)→(X→X)). The empty list nil
corresponds to 0̄ and list-consing a.l to the successor function:
nil ≡ λX.λf.(λx.x)
a.l ≡ λX.λf.λx.f(a)((l(X)(f))(x)).
Consequently we have
a.nil ≡ λX.λf.λx.f(a)(x),
a.b.nil ≡ λX.λf.λx.f(a)(f(b)(x)), and
a1 .. . . .an .nil ≡ λX.λf.λx.f(a1 )(f(a2 )(. . . (f(an )(x)). . . ))
Recursive definitions of list functions f : A list→B with f (nil) = g and
f (a.l) = h(f (l)) where g ∈ B and h ∈ B→B would be expressed by λl.l(B)(h)(g).
The question arises whether this method can be generalized to arbitrary recursive types. See
Section 4.4 for more discussion of inductive definitions.
As we have seen dependent types give us enough freedom to overcome the weakness of Simple
Type Theory discussed in Section 3.2.6. By only six axioms one may express all the important data structures of programming languages, all kinds of mathematical objects and the full
(higher order) propositional calculus. It is powerful enough for arithmetic but still decidable
since fixed point operators are excluded. Many of the good properties of Simple Type Theory
like Strong Normalization and the Church Rosser Property remain. So it seemed that the
theory of dependent types would be the solution in the search for a constructive foundation of
mathematics.
Exercise 3.3.4 Show how to simulate the disjoint union of two types A and B in the theory of
dependent types.
3.3.3
Girards Paradox
The reason why the Martin-Löf’s early theory of dependent types is not being used as a constructive foundation of mathematics is a paradox that had been discovered shortly after Martin-Löf
wrote down his first notes [ML70]. Together with dependent types the axiom U∈U allows to
formulate a counterpiece to the paradox of “largest ordinals” in set theory, a fact which was
first discovered by Girard.
Example 3.3.16 Consider the set of all well-ordered types hA, <A i where <A is a transitive
and well-founded order relation20 . Define an order <U on this set by
hA, <A i <U hB, <B i iff ∃f : A→B.(f order − isomorphic ∧ ∃b : B.∀a : A.f (a) <B b).
Then <U is a transitive and well-founded order relation on U and thus hU, <U i belongs to
the set of well-ordered types. Furthermore, hU, <U i is a maximal element of this set, i.e. we
can prove hA, <A i <U hU, <U i for each well-ordered type. Consequently hU, <U i <U hU, <U i
must be true which contradicts well-foundedness of <U .
20
An order relation <A on A is well-founded if there is no infinite decreasing sequence relative to <A :
“¬∃f : N →A.∀n.f (n + 1) <A f (n)”.
3.4. A SYSTEMATIC APPROACH
61
The axiom U∈U, although avoiding Russel’s Paradox, allows to formulate the above paradox within the Mathematics of U∈U. Thus the Theory of dependent types with U∈U is selfcontradictory, i.e. inconsistent. This incident shows how important it is to prove the correctness
of a theory even after only slight modifications.
Having discovered an inconsistency in an otherwise extremely promising theory there are two
ways to proceed:
Safety first and back to the roots: this means to retreat to a safe position in the theory
and start again with a new theory. This is the path we will follow in the rest of this book
when studying Martin-Löf’s predicative theory of types and the Type Theory of NuPRL.
Fix the bug and keep the theory: This means to essentially keep the theory as it is while
performing only slight modifications in order to avoid the inconsistency. This was successfully done by Girard in the development of System F [Gir71, Gir86, GLT89]..
He did this by carefully looking at what needs to be avoided. Clearly one does not want
U∈U and (A→ U)∈U. However, quantifying over types or propositional functions shall still
be possible and thus constructs like X:U→B or X:(A→U)→B must be definable without
requiring U and A→U to be types. According to these considerations the syntax of the
above theory has to be modified in a way that no contradiction can arise anymore.
In our notation the rules are:
H ` X:U→B ∈U by formation
· H, X:U ` B ∈U
H ` X:(A→U)→B ∈U by formation
· H ` A ∈U
· H, X : A→U ` B ∈U
Note that in X:U →B and X:(A→ U) →B the constructs U and A→ U are used only
as syntactic devices and not as types. To avoid confusion the theory of species uses special
syntactic notations x:A, where x, y, z denote individual variables while X, Y, Z denote
species variables in ∀XA .B, an abbreviation for ∀X:A→U.B (or X:(A→U)→B).
In order to justify that a theory coming out of the above rules is in fact sensible a complicated metatheory is needed which has not been properly done yet. However, it is unlikely
that the theory contains another bug and thus it is already being used as a powerful theory producing all kinds of types from scratch as described above. In particular there is no
need for any primitive type which makes it quite appealing as a constructive fundament of
mathematics. See [Gir71, Gir86, GLT89, CH85, CH88] for further details of this approach.
3.4
A systematic approach
Simple Type Theory and the mathematics of U∈U provide a lot of useful ideas how to develop
a fundamental theory for automating mathematics and programming. As discussed in the
previous sections, both theories themselves are not appropriate for this purpose. Nevertheless,
our investigation of the mathematics of U∈U showed that in principle it is possible to reach this
goal. The path indicated by this theory should therefore be used as a guideline for a systematic
62
CHAPTER 3. TYPED THEORIES
development of a Type Theory that can be used for both checking and developing proofs for
all kinds of mathematics, including programming problems.
The Type Theory we will develop in the rest of this book is based on Martin-Löf’s Intuitionistic
Theory of Types, first presented in [ML82], and contains some fundamental differences with
earlier treatments. In particular, computation is no longer a metamathematical feature but
directly expressible in the theory. Thus, type theory is now a constructive semantic theory, i.e.
a theory reflecting the semantics of the terms it deals with. As a result, we have to consider
not only a formal language and inference rules also concepts for expressing semantics within a
theory.
In this section we will first explain the general principles of constructive semantic theories and
then describe how Type Theory is build up as a semantic theory and a proof calculus for it.
The Type Theory of the NuPRL proof development system which we will describe in Chapter
4 will is developed according to these principles.
3.4.1
Martin Löfs constructive semantic theory
The methodology for building constructive semantic theories presented by Martin-Löf evolved
from Tait’s computability method for proofs of strong normalization. It can be applied not only
in mathematics and computer science but also in other sciences dealing with formal languages
(like linguistics) as well.
1. Fix the formal language of the theory by defining expressions and binding occurrences of
variables.
2. Divide expressions into values (canonical expressions) and expressions relating to values
(noncanonical expressions). In a larger theory this is usually done by tables.
3. Fix the semantics of the expressions by giving computation rules for noncanonical expressions in the form of term-rewriting-rules. The computation rules define a reduction
relation −→ on expressions.
4. Introduce judgements about expressions and define their meaning. Define them explicitely
for canonical expressions and deduce the meaning of judgements about noncanonical expressions from their normal forms.
5. Introduce hypothetical judgements to allow reasoning under assumptions and define their
meaning.
Simple Type Theory could have been developed as a semantic theory if we would include the
reduction rules of the λ-calculus.
Example 3.4.1 In Simple Type Theory we had canonical expressions S→T and λx.b and
f (a) as noncanonical expression. The x in λx.b was a binding for all occurrences of x in b.
A computation rule for f (a) follows from the untyped λ-calculus:
“reduce f until it has the form λx.b and then replace f (a) by b[a/x]”.
The only judgement we had was a typing t ∈ T . A hypothetical judgement is the logical
counterpart of a proof goal.
3.4. A SYSTEMATIC APPROACH
63
The notion of judgements should not be confused with that of propositions. A proposition is
a term of a formal language which, when interpreted, may be true or false while a judgement
states what is true in the theory. The meaning of a judgement must therefore be properly
defined before we can build a proof calculus for the theory.
Judgements will constitute the claims of a formal proof although they cannot themselves be
part of it. Nevertheless, the definition of proofs and the rules of inference have to respect the
meaning of judgements and hypothetical judgements.
3.4.2
Semantics of type-theoretical expressions
In Type Theory canonical expressions either denote type constructors like x : S→T, IN or
constructors for canonical elements of a certain type like λx.b. Noncanonical expressions like
f (a) are also called destructors of elements.
When introducing new types we will try to avoid introducing redundant type constructors,
i.e. those that could be simulated by others. Otherwise proofs about important metatheorems
would have too many cases to be investigated. For the same reason the general policy will be
to define only one element constructor and one destructor for each new type, if that is possible.
21
This does, however, not mean that a user of Type Theory will be forced to use only these
expressions. Quite the reverse, syntax and semantix are, at least in principle, open ended since
a user is allowed to extend the predefined language of Type Theory by abbreviations using
definitional equality. Such an abbreviation is introduced by
new-expression ≡ term
where new-expression may be any text in the alphabet which is available and term is an expression in Type Theory including the abbreviations so far. The semantics of the abbreviation
follow immediately from the term it is defined by. Definitional equality is a purely syntactical
matter since it relates linguistic expressions. The equality is intensional and not to be confused
with equality of values which is extensionally defined by the computation rules.
For the semantics of Type Theory lazy evaluation is essential. λ-abstraction makes λx.f (x)
a canonical expression regardless of the fact whether the inner term b is canonical or not.
Thus Type constructors define lazy elements. As a consequence, reduction will have reached
a normal form where in principle further reduction would be possible. This is reflected in the
computation rule for function application:
In f (a) reduce f until it has the form λx.b and then replace f (a) by b[a/x]
For (λx.λy.x)(g(z)) reduction will stop at λy.g(z) although g(z) may be reduced. Thus, even
if g(z) would not be normalizable in the original sense of the λ-calculus we would still reach
normal form. While this decision was made in favour of efficiency of the reduction mechanism
it lays a heavier burden on the inference calculus if we want the results to be meaningful.
Principle 1 Type Theory uses lazy evaluation
21
The only exception from this rule is adding standard constructs for user convenience. Essentially this is,
however, nothing but an explicit “encoding” of abbreviations and their derived rules. The NuPRL type of
integers in Section ?? is an example.
64
CHAPTER 3. TYPED THEORIES
3.4.3
Judgements in Type Theory
So far the only judgement we had in the type theories so far was a typing t ∈ T saying that
a certain expression is a member of a type or, if T is U that the expression denotes a type. In
order to reason about semantics we must also be able to make judgements about values, i.e.
we must be able to judge that two expressions have equal values. This may, of course, strongly
depend on the type we are dealing with. Two sequences of rational numbers may be different
as sequence but if we look at the real number they define by their limits then they may denote
the same. Therefore the type of the objects to be compared must be included in the judgement.
In Type Theory there are the following four forms of judgements:
1. A type: “A is a type” (Typehood).
2. A = B: “A and B are equal as types” (Type equality).
3. a ∈ A: “a is an object of type A” (Membership).
4. a = b ∈ A: “a and b are equal objects of type A” (Member equality).
Now let us explain what the meaning of these judgements shall be. According to Bishop’s
constructive set theory [Bis67] a set (type) A is defined by prescribing how to build (canonical)
members and when two (canonical) elements of A are equal. Thus the definition of a type must
automatically induce a notion of membership and equality of members. Classical set theory
(see e.g. [Sup72, Qui63]) defines two sets to be equal if they have the same members. Thus
equal types must have the same membership and equality although the the converse may not
be true. Obviously, the equality judgements must be equivalence relations on terms and all
judgements must respect the semantics of expressions.
These consideration led to the following general method a formal definition of the judgements
has to follow.
1. A type: Canonical types are given by declaring a particular set of canonical expressions
to denote types (e.g. IN, x : A→B, A#B). A is a type if it reduces to a canonical type.
2. A = B holds iff A and B reduce to the same canonical type22 .
3. a ∈ A iff A is a type and a reduces to a canonical value in A. Canonical members of a type
are defined inductively (e.g. 0∈ IN, λx.b ∈ y : S→T iff ∀a.(s ∈ S) ⇒ b[s/x] ∈ T [s/y]).
4. a = b ∈ A iff a and b reduce to the same canonical value in A, which again needs an
inductive definition.
Hypothetical judgements in Type Theory will have a form corresponding to sequents:
x1 :A1 , . . . , xn :An ` J
“under the assumptions xi :Ai we judge J”.
Hypothetical judgements have to be functional23 and extensional, i.e. for all canonical ai ∈ Ai
the judgement J[ai /xi ] is true and if ai and a0i are objects (possibly noncanonical) of equal
value in Ai then J[ai /xi ] = J[a0i /xi ].
22
This requires a long inductive definition since “the same” is to be taken in a semantic sense: If, for instance
A reduces to x : S→T and B reduces to x0 : S 0 →T 0 then
A = B iff S = S 0 ∧ ∀s, s.(s = s0 ∈ S) ⇒ T [s/x] = T 0 [s0 /x0 ]
23
See [CAB+ 86] pp. 141f or [ML84] pp. 16ff for a detailed definition.
65
3.4. A SYSTEMATIC APPROACH
A
A
A
A
is
is
is
is
A type:
a datatype (set)
a proposition
a problem (task)
an intention (expectation)
a
a
a
a
is
is
is
is
a∈A
an element of A
a proof (construction) for A
an method to solve A
a method of fulfilling
(realizing) A
A
A
A
A
is
is
is
is
nonempty (inhabited)
true
solvable
fulfillable (realizable)
Table 3.1: Interpretations of Judgements
3.4.4
Propositions as types
Type Theory, as we mentioned before, shall serve as a unified fundamental theory for automating mathematics and programming. We will now investigate, how the above judgements can
be used for that purpose. Each of them admits several different interpretations as shown in
Table 3.1.
The third column represents a different reading of the second where some information (about
the specific member) is missing. Its consequences for the proof calculus will be discussed in
Section 3.4.7. The last interpretation was suggested by Heyting [Hey31] and the third by
Kolmogrorov [Kol32]. Today, “a is a method to solve the problem A” can be read as “a is
a program which meets the specification A” which means that Type Theory will in fact be
applicable to programming24 . The second, logical interpretation is what we already know as
Curry-Howard Isomorphism and indicates that Type Theory can express logics as well. To
distinguish proofs of judgements from those of propositions (a term which we judge to be a
proof of the proposition) will will often use the word “construction” for the latter if confusion
might appear.
In Section 3.2.6 we have investigated the implicational component of the Curry-Howard Isomorphism. Knowing that a proposition is true if and only if we can find a proof for it we will
now continue this investigation by interpreting the meaning of the logical operations:
Conjunction To prove A ∧ B we must be able to prove A and B. If a is a proof for A and b one
for B then ha, bii is all the evidence we need to know that A ∧ B is true. Thus, essentially
A ∧ B behaves like a product type.
Disjunction Provided a constructive interpretation of ∨ (the other can be simulated with ∧
and ¬) a proof of A ∨ B must either prove A or B. Thus the set of all proofs of A ∧ B is a
disjoint union of the sets of proofs for A and B.
Implication In order to prove P ⇒ Q we need to know how a proof p of P can be transformed
into a proof q of Q. Apparently, the transformation must be a function from the set of
proofs of P into those of Q. Thus P ⇒ Q behaves identical to a function space.
Negation ¬A is a shorthand for A ⇒ Λ
Falsehood Λ is a proposition that does not have any proofs. It thus resembles the empty set
and can be represented by an datatype which has no members.
24
See Section 4.3 for a discussion of the impacts of this interpretation.
66
CHAPTER 3. TYPED THEORIES
Universal Quantification To prove ∀x : A.B we need a general method for proving B(x) for
any x ∈ A. Essentially this method is a function creating a proof B(x) for all inputs x ∈ A.
The output type of this function depends on the input value so the only appropriate type
concept corresponding to ∀x : A.B is a dependent fucntion type x : A→B.
Existential Quantification To prove ∃x : A.B we must be able to provide and element x of
A and a proof b for B(x). Thus essentially a proof of ∃x : A.B consists of a pair ha, bii
where b is a proof of B(a). The datatype concept behind these pairs is, as in the case of
functions, the notion of a dependent product. The nonconstructive interpretation of ∃ can
again be simulated.
Thus, if Type Theory can provide proper definitions of (dependent) functions, (dependent)
products, disjoint union, and of an empty type, then it can simulate all logical connectives and
would allow to automate logic within Type Theory.
This leaves one problem open. How do we integrate propositions into type theory? Looking
at the above similarities we certainly do not want a separate term category like proposition
besides members and types. Instead, we simply identify propositions with types. To be more
specific, we syntactically identify a proposition with the type of all its proofs. This is the
propositions-as-types principle on which Intuitionistic Type Theory is based.
Principle 2
Propositions are Types in Type Theory
There may be philosophical objections to this principle since propositions and types are conceptually quite different. One should, however, keep in mind that Type Theory is intended to
make mathematical reasoning accessible to computer systems which in the end do nothing but
symbol manipulation and cannot handle philosophical considerations anyway.
3.4.5
Propositional equality
In our investigation of Judgements in Type Theory we have discussed the need of having equality
judgements in the theory. What is still missing, however, is a capacity to reason about equality
within a formal proof. How shall we, for instance, reason that a λ-term describes a function
and not just an “operator” or “algorithm”? In the definition of the equality judgement this
may be expressed properly but how can we conclude f (a) = f (a0 ) for f ∈ A→B if we know a
and a0 to have equal values in A?
Equality reasoning is essential to most of mathematics and programming and we must therefore
be able to use equality in the assumptions of a proof. Since typings are all that is allowed in the
hypotheses of a proof and we do not intend to burden us with new concepts, we will introduce
a type for propositional equality and denote it by a=b in A. This type represents one of the
most basic logical propositions. There is hardly another proposition which is as important.
There will be one canonical member which we call axiom. All proofs will eventually reduce to
axiom, thus bearing evidence that a=b in A is true.
The type a=b in A is not to be confused with the judgement a = b ∈ A. Note, however, that
“a=b in A true” is a judgement that is intended to be equivalent to a = b ∈ A. Thus the
judgement p ∈ a=b in A will be true if p reduces to axiom and a = b ∈ A. We will include
this in our formal definition in Section 4.1.
67
3.4. A SYSTEMATIC APPROACH
3.4.6
A cumulative hierarchy of universes
While typehood and type equality can be defined with complete freedom a formal proof system
requires a representation of “A type” and “A = B” in the formal language. Knowing that A ∈
U and A = B ∈ U can be used for that purpose we again have to face the problem that U itself
must be an expression of the formal language.
If we allow the theory to contain dependent types, as we wish to, then allowing U to be a type
which is a member of U leads to a paradoxon (c.f. Section 3.3.3). On the other hand, dependent
types force us to make judgements about the typehood of terms like A→U25 and in the end we
have to assign a type to U. The easiest solution to this problem is to view A→U as a “large”
type, i.e. as a member of some higher universe which we call U2. This consideration leads to a
hierarchy of types U1:=U, U2, U3, etc., viewing U1 itself as a collection of “small” types.
This idea was not entirely new. Looking into “Principia Mathematicae” [WR25], the root of
modern mathematics, we already find a type structure though a complicated one. A simplification by Quine [Qui63] lead to to a cumulative theory of types by which indexed type constructs
like A→i B could be avoided. The clue is not only to have U1 as a member of U2 but also of a
subset of it. Thus every universe contains all the universes below it and their elements.
∈
∈
U1 ⊂ U2 ⊂ U3 . . .
In some sense this is quite close to U∈U but avoids its problems. The Ui are called universes of
hierarchies.
3.4.7
A calculus for proof development
Table 3.1 in Section 3.4.4 already indicated that besides typehood and membership there is a
third concept in between the two. This becomes particularly interesting after we have accepted
the propositions-as-types principle.
Example 3.4.2 Consider a proof for the judgement “a=b in A true”. By the propositionsas-types principle this is represented by p ∈ a=b in A where p reduces to axiom.
The term p will entirely depend on the proof we have to give for a being equal to b. If, for
instance, we already know p1 ∈ a=c in A and p2 ∈ c=b in A then we could apply the rule
of transitivity which forces p to be something like trans(p1 ,p2 ).
The important point is that p must already have this form in order to get a valid proof.
The matter becomes even more complicated if we think of all the other rules that could be
applied for proving a logical proposition. We would be forced to calculate a construction (a
proof term) beforehand according to the proof rules we intend to apply and then redo the proof
in the formal system just to check the construction correct. This definitely would be double
work although proof checking (i.e. type checking) can be partially automated26 .
25
The judgement about x : A→B can be defined in terms of B[a/x] which is a member of U. The formal proof
cannot use β-reduction without typing B as member of A→U which leaves the question of the nature of A→U
open.
26
But see Section 3.2.2
68
CHAPTER 3. TYPED THEORIES
What we really want to prove in the above example is that a and b are equal and not that a
certain construction is in fact a proof element for a=b in A. That is, we would like to develop
a proof (construction) of a proposition in the formal theory while developing the formal proof
(of the judgement). In other words, we would like to make the distinction between judgements
and propositions as invisible as possible27 .
This requires on major change in the representation of the judgements in the formal proof
theory. Instead of p ∈ a=b in A we write a=b in A [ext p] to indicate that we intend to
hide the evidence p.
For the theory itself this change has no effect at all because it is just a different representation
of the same judgement. In connection with a system that implements Type Theory this change,
however, becomes important. A goal
x1 :A1 ,. . . , xn :An ` T [ext p]
is to be read as “under the assumptions xi :Ai we judge that T is inhabited” and the evidence
p does not have to be provided beforehand but can be extracted from the proof. p is therefore
called the extract term of the proof. It remains hidden until completion of the proof.
Technically this means applying the proof rules top down as if they would apply to the types
only. Once the formal proof is finished the resulting proof tree is used to construct the extract
term bottom up according to the kind of terms each individual rule requires to actually lead to a
valid proof. Constructing the extract term from a complete proof tree can easily be automated.
3.4.8
Formal proofs in Type Theory
We will now summarize the above considerations and show how they can be used in a proof
theory which, if implemented, promises to yield sufficient support for automating mathematics
and programming.
As we have seen, each equality judgement a = b ∈ A is properly represented by the judgement
p ∈ a=b in A. Typehood “A type” can be expressed by “A ∈Ui” for some universe Ui. For
the formal proof system we can therefore reduce all four kinds of judgements to a typing and
use the concept of formal proofs as defined before (Definitions 3.1.6 and 3.3.5). Typings will
be written as statements about inhabitance of a type.
Principle 3
Judgements in Type Theory are represented by goals of the form T [ext p] .
Consequently we get the following representations of the four kinds of judgements as proof
goals.
1. Ui [ext A] will be used instead of “A type”. (A is a witness for Ui being inhabited, thus
a type).
2. A=B in Ui [ext p] instead of A = B.
3. A [ext a] instead of a ∈ A. (A is inhabited which is proven by a).
27
and turn what was formerly a theory for proof checking (in the classical sense) into one for proof development
3.4. A SYSTEMATIC APPROACH
69
4. a=b in A [ext p] instead of a = b ∈ A.
Note that although an explicit version of a ∈ A does not occur in the formal proof system
it can be simulated by a=a in A [ext p] which we will abbreviate by a in A [ext p] .
Thus, without the aspect of proof construction, a in A [ext p] and A [ext a] would be
redundant proof goals.
If the extract term is not of particular interest (as often in a=a in A [ext p] ) we omit it.
This reflects the fact that a system would show extract terms only on demand.
In the proof calculus we use four kinds of rules for each type construct.
1. Type formation rules describe how a certain type can be formed from certain other types.
Since types are members of some Ui these can be viewed as introduction rule for the type
constructor as a member of Ui. These rules apply to goals like Ui [ext A] and A=B in
Ui [ext p] .
2. Introduction rules for canonical members say how canonical members of a certain type are
to be constructed. These rules apply to goals A [ext a] and a=b in A [ext p] where
a and b will be canonical members of A.
3. Elimination rules for determine when a noncanonical member belongs to a certain type.
Applied to a=b in A [ext p] where a and b are noncanonical it may be interpreted as
an introduction rule for the destructor. On a goal A [ext a] it extracts a noncanonical
member A which is possible only by operating on a variable of the corresponding type
which is defined in the hypothesis list.
4. Computation rules relate introduction and elimination rules by describing how a noncanonical member operates on the corresponding canonical one. They apply to goals a=b in A
[ext p] where either a or b is a redex and reduce it to its contractum.
There will be a few other rules serving miscellaneous purposes like the hyp rule. Since for each
construct the actual rule name can be determined from the context once its kind is given we will
use generic names like intro instead of →-intro. Type formation is the same as introducing
a member of the type Ui and will also be denoted by intro. In general the name intro is
used when we break down the conclusion of a goal. Sometimes we have to give an object to be
introduced as a parameter. The elim rules operate on a hypothesis which we have to identify
by either its position in the hypothesis list or the variable being declared. reduce rules perform
computation steps and need a parameter to determine the term to be reduced. Some rules have
keyword parameters of the following form.
• new x1 ,. . . ,xn is used when new variables may have to be introduced if the variable
names derived from the conclusion (e.g. the x from x:A→B) already occur.
• using T over z.T is used when judging the equality of noncanonical forms in dependent
types. using T specifies T to be the type of the principal argument. over z.T specifies
the dependence of the type T over which the equality is being judged on the principal
argument of the form. Each occurrence of z in T indicates such a dependency
• at Ui determines the universe level at which any type judgements in the subgoals are to
be made. The default is U1.
Each rule must be given in its most general form. Optional parameter are enclosed by square
brackets as in [new x]. If the extract term is trivial (i.e. axiom) it will be omitted.
70
3.5
CHAPTER 3. TYPED THEORIES
References and further reading
There are various books and tutorials containing general introductions to Type Theory. The
theory described here is derived from Martin-Löf’s Type theory [ML73, ML84, NPS90, BCM88a,
BCM88b, Bac89] but we use the syntax of the NuPRL system [CAB+ 86] which we will describe
later in more detail.
The book of Girard [GLT89] contains a different Type Theory but is worth looking up for
detailed proofs about properties of Type Theory. Another source is the book of Andrews
[And86]
Besides an unpublished manuscript of Martin-Löf [ML70] the book of Stenlund [Ste72] gives a
good introduction into Simple Type Theory and the theory of species.
Alternative theories based on Martin-Löf’s original theory are described in [Gir71, Gir86,
GLT89, CH85, CH88].
Martin Löfs constructive semantic theory and its impacts on the development of Type Theory
are implicitely contained in [ML84] and Chapter 8 of [CAB+ 86]. Several individual articles
[All87a, All87b, Con89, CH90b, Smi84] give additional insights about the semantics of Type
Theory.
Chapter 4
The Type Theory of NuPRL
Following the methodology developed in Section 3.4 Type Theory can now be developed brick
by brick. In this chapter we will introduce the type theory of the NuPRL1 proof development
system and show how it can be used as a unified fundament for mathematics, logic and programming. We will begin with an in-detail description of the most fundamental constructs.
Further types will be added according to our needs.
4.1
Basic constructs
According to our discussion in Section 3.4 Type Theory should provide at least propositional
equality, universes, a type of (dependent) functions, (dependent) products, and disjoint union.
All these types can be introduced straightforwardly.
Propositional equality, as mentioned in Section 3.4.5 is the essential type for reasoning about
values of expressions. “a=b in A” represents the statement “a and b are equal members of A”.
It is inhabited by the element axiom if the statement is true and empty otherwise.
Universes (c.f. Section 3.4.6) Ui denote the collection of all types of level i. All canonical types
are canonical members of some universe Ui including the universes of lower level and their
members. Specific type destructors do not exist (so far).
The need for dependent function spaces as types for λ-terms is obvious. We will keep the
notations x:A→B (or A→B, if there is no dependency),2 λx.b and f (a).
Another fundamental concept in both mathematics and programming is the formation of tuples.
Set Theory, for instance, starts with the definition of unordered pairs in order to derive other
concepts like ordered pairs, functions, etc. All major programming languages use arrays or
record structures. Essentially, tupling can be reduced to forming pairs ha, bii of objects a and b.
Forming the product A#B of two types A and B is the corresponding type construct. Complex
structures like n-tuples or arbitrary records can be constructed by nested pairs. To undo pairing
1
The name NuPRL stands for Proof (or Program) Refinement Language, version ν (the “new”, nearly
ultimate version after λ-PRL) which has been developed at Cornell University in the early 1980’s [CAB + 86]
2
It should be noted that due to the set-theoreticQview of functions as sets of pairs hargument, valueii the type
x:A→B can also be denoted as infinite product a∈A B(a). Many authors (see e.g. [ML82, ML84, GLT89,
NPS90]) use this notation although the use of λ-terms as canonical members suggests an operation or program
rather than a set of pairs.
71
72
CHAPTER 4. THE TYPE THEORY OF NUPRL
in a uniform way we use the term spread(p;u,v.t) (c.f. Example 2.6.17) which should be read
as “In t instantiate u, v such that p = hu, vii”. To be able to represent programming language
constructs like variant records we also introduce dependent product types: x:A#B 3 denotes the
type of all pairs where the value of the first component determines the type of the second.
Disjoint union A|B of two types A and B represents a type whose elements can be determined
to come from either A or B.4 Canonical elements must therefore yield information about the
origin of an element. We use inl(a) and inr(b) to denote the left and right “injection”. To
undo injection we have to decide where an element d came from. decide(d;x.s;y.t) is to be
read “if d evaluates to inl(x) then result s; if d evaluates to inr(y) then result t”. Obviously,
disjoint union cannot have any meaningful dependencies.
4.1.1
The semantic theory
Following Martin-Löf’s prescription (c.f. Section 3.4.1) we will now develop a semantic theory
for propositional equality, universes, a type of (dependent) functions, (dependent) products,
and disjoint union.
Definition 4.1.1
An expression is
1. A variable5 ,
2. (t), where t is an expression,
3. Ui, where i is a positive integer constant,
4. axiom,
5. a=b in A, where a, b and A are expressions,
6. an application t(a) where t and a are expressions,
7. an abstraction λx.b where b is an expression and x a variable,
8. x:A→B and A→B, where A and B are expressions, x a variable,
9. a pair ha, bii, where a and b are expressions,
10. a spread term spread(p;u,v.t), where p and t are expressions and u and v are variables,
11. x:A#B and A#B, where A and B are expressions and x is a variable,
12. inl(a) and inr(b), where a and b are expressions,
13. decide(d;x.s;y.t), where d, s and t are expressions and x and y are variables,
14. A|B, where A and B are expressions.
P
Category theory describes dependent products as infinite disjoint unions a∈A B(a) but this is a rather
misleading notation. In order to express disjoint union of sets which are not really disjoint like IN + IN both sets
need to be tagged (IN1 + IN2 ) to become distinct. Tagging, however, means adding something to an element
(01 ∈ IN1 ), thus making it essentially a pair.
4
Forming an arbitrary union of two types as set theory does is a highly nonconstructive operation. It would
mean clashing together two types without leaving a chance to decide from which type an element came from.
A computable destructor for such a type cannot exist.
5
Variables are written as identifiers with distinct identifiers indicating distinct variables. An identifier is any
string of letters, digits, underscores, or at-signs (@) which starts with a letter. The only identifiers which cannot
be used are operator names like inl and other identifiers which already have a fixed meaning.
3
73
4.1. BASIC CONSTRUCTS
Lower Precedence
=, in
#, →, |
inl, inr
λx.
(a) as in f (a)
left associative
right associative
———
———
———
Higher Precedence
Figure 4.1: Operator precedences
Parentheses must be used to resolve ambiguous notations correctly. By precedence conventions
we may lessen the need for parentheses. The equality sign = should have the lowest precedence.
λx.f (y) should abbreviate λx.(f (y)) and not (λx.f )(y). Thus function application binds
stronger than λ-abstraction. Typically, 2-ary operations are understood left associative (i.e.
6-2-3 is the same as (6-2)-3). Type constructors, however, must are right associative: λx.λy.t
∈ A→B→C is the same as λx.(λy.t) ∈ A→(B→C). Figure 4.1 gives a complete list of
precedences.
Open terms, i.e. terms containing free variables, cannot be considered executable since a value
cannot be properly defined. A variable x occuring in a term t occurs free unless it becomes
bound by a binding operator.
Definition 4.1.2 Binding occurrences of variables in expressions:
• A variable x occurs free in x; no other variables occur at all.
• In λx.b the x in front of the dot and all the free occurrences of x in b become bound. Free
occurrences of variables y different from x remain free in λx.b.
• In spread(p;u,v.t) the u and v in front of the dot and all occurrences of u and v in t
become bound.
• In decide(d;x.s;y.t) the x and y in front of the dot and all occurrences of x in s and
of y in t become bound.
• In x:A→B and x:A#B the x in front of the colon and all the free occurrences of x in
B become bound. Free occurrences of variables y different from x remain free in x:A→B
and x:A#B.
• No variable becomes bound by forming (t), a=b in A, axiom, t(a), A→B, ha, bii, A#B,
inl(a), inr(b), or A|B.
Among the closed terms we distinguish canonical and noncanonical expressions. 6 Terms
with the outer form f (a), spread(p;u,v.t), or decide(d;x.s;y.t) are noncanonical. All
other forms are canonical. Thus λx.b, ha, bii, inl(a), and inr(b) are canonical expressions
regardless of the fact whether a or b are in canonical form or not. We have defined them as
lazy elements.
Definitions 4.1.1 and 4.1.2 and the separation of canonical and noncanonical terms can be
summarized in a table as in Figure 4.2 which simply lists all terms and binding occurrences.
Variables written below a term indicate where the variables become bound. Diamonds ()
6
It does not make sense to call an open expression canonical because it has no value
74
CHAPTER 4. THE TYPE THEORY OF NUPRL
canonical, if closed
(types)
(elements)
x
x:A→B
x
x:A#B
x
x
A→B
x
A#B
noncanonical, if closed
(t)
λx.b
t(a)
ha, bii
spread(p;u,v.t)
x x
u v u
v
A|B
inl(a)
a=b in A
axiom
Ui
inr(b)
decide(d;x.s;y.t)
x x y y
————
————
(all canonical types)
x, y, u, v range over variables, a, b, d, p, s, t, A, B range over terms, i over positive integer constants.
Variables written below a term indicate where the variables become bound.
Diamonds () indicate the positions of principal arguments in noncanonical expressions.
Figure 4.2: Terms
indicate the positions of principal arguments in noncanonical expressions, i.e. arguments which
play the key role in the evaluation procedure. Note that although we have written types and
their members separately, there is no distinction between types and objects on the syntactic
level. Such a distinction can only be made through judgements, i.e. semantical constructs.
An immediate consequence of defining canonical members as lazy elements is that the computation rules perform lazy evaluation by only looking at the outer structure of a term.
Definition 4.1.3 Computation rules for the functions, products and unions
• In f (a) reduce f until it has the form λx.b and then replace f (a) by b[a/x].
• In spread(p;u,v.t) reduce p until it has the form ha, bii and then replace spread(p;u,v.t)
by t[a, b/u, v].
• In decide(d;x.s;y.t) reduce d until it is in canonical form. If d=inl(a) then s[a/x] is
the contractum, if d=inr(b) then t[b/y] is the contractum.
Essentially these rules describe how to rewrite redices into their contracta. Thus, given a table
of redices and their contracta, as in Figure 4.3, these three rules may be considered as instances
of a general evaluation procedure which is given in Figure 4.4.
Comparing this algorithm with the reduction rules for the untyped λ-calculus (Definition 2.6.6)
one may notice that the reduction rules of type ξ and µ have been abandoned while the α, β,
ν, ρ, and τ -reduction is still in force. In contrast to the simple typed theories, therefore,
Figure 4.3: Redices and contracta
Redex
Contractum
(λx.b)(a)
b[a/x]
spread(hha, bii;u,v.t)
decide(inl(a);x.s;y.t)
t[a, b/u, v]
s[a/x]
decide(inr(b);x.s;y.t)
t[b/x]
x, y, u, v range over variables, a, b, d, f, p, s, t, A, B range over terms.
75
4.1. BASIC CONSTRUCTS
(semantical) equality of expressions cannot be defined by simply saying “a and b are equal if
they reduce to the same value” which we could do because of the Church-Rosser property. For
this reason the notion of equality must be contained in the definition of judgements.
Four judgements “T type”, “S = T ”, “t ∈ T ”, and “s = t ∈ T ” are defined as predicates on
possibly open terms. It will turn out that these predicates will hold only for closed terms. As
such they constitute the NuPRL type system.
Definition 4.1.4 Judgements
β
Let −→ denote the reduction relation induced by the evaluation procedure and the table of
redices and contracta. The predicates “ T type ”, “ S = T ”, “ t ∈ T ”, and “ s = t ∈ T ”
are defined by mutual induction according to the rules given in Figures 4.5 and 4.6.
One should keep in mind that judgements express the semantics of NuPRL’s type theory and
should not be confused with the notion of provability.
Lemma 4.1.5
1. the relation S = T is transitive and symmetric,
β
2. for all terms S and T : S = T if and only if there is a term S 0 such that S −→ S 0 and
S0 = T ,
3. the relation s = t ∈ T is transitive and symmetric in s and t,
β
4. for all terms s, t, and T : s = t ∈ T if and only if there is a term s0 such that s −→ s0
and s0 = t ∈ T ,
5. for all terms s, t, and T : s = t ∈ T implies “T type” (T = T ),
6. for all terms s, t, S, and T : if s = t ∈ T and S = T then s = t ∈ S,7
4.1.2
The proof rules
According to the principles discussed in Section 3.4.8 all the judgements can be properly represented in the proof calculus by goals of the form T [ext p] which is another way of writing
“p ∈ T ” and better fits the concept of proof development. The judgements have been defined
7
Therefore the membership relation for A→B and A#B is induced by the corresponding membership relation
for the dependent version.
Figure 4.4: The general evaluation procedure
Given a (closed) term t, evaluate as follows:
• If t is canonical then terminate with result t.
• Otherwise, execute the evaluation procedure on each principal argument of t, and if each has a
value, replace the principal arguments of t by their respective values; call this term s.
- If s is a redex then continue by evaluating the contractum of s.
- If s is not a redex then terminate without a result; t has no value.
76
CHAPTER 4. THE TYPE THEORY OF NUPRL
T type iff T = T .
S = T iff exists A, A0 , B, B 0 , x, x0 .
β
β
β
β
(S −→ x:A→B or S −→ A→B) and (T −→ x0 :A0 →B 0 or T −→ A0 →B 0 )
and A = A0 and (for all a, a0 . B[a/x] = B 0 [a0 /x0 ] if a = a0 ∈ A)
or exists A, A0 , B, B 0 , x, x0 .
β
β
β
β
(S −→ x:A#B or S −→ A#B) and (T −→ x0 :A0 #B 0 or T −→ A0 #B 0 )
and A = A0 and (for all a, a0 . B[a/x] = B 0 [a0 /x0 ] if a = a0 ∈ A)
β
β
or exists A, A0 , B, B 0 . (S −→ A|B) and (T −→ A0 |B 0 ) and A = A0 and B = B 0
β
β
or exists a, a0 , b, b0 , A, A0 . (S −→ a=b in A) and (T −→ a0 =b0 in A0 )
and A = A0 and a = a0 ∈ A and b = b0 ∈ A0
β
β
or S −→ Ui and T −→ Ui.
x, x0 , y, y 0 range over variables, a, a0 , b, b0 , A, A0 , B, B 0 , s, t, S, T range over possibly open terms, i, j over positive integers.
Figure 4.5: The type equality judgement
t ∈ T iff t = t ∈ T .
s = t ∈ A if A = B and s = t ∈ B.
β
β
s = t ∈ x:A→B iff x:A→B type and exists y, y 0 , b, b0 . s −→ λy.b and t −→ λy 0 .b0
and (for all a, a0 . b[a/y] = b0 [a0 /y 0 ] ∈ B[a/x] if a = a0 ∈ A).
β
β
s = t ∈ x:A#B iff x:A#B type and exists a, a 0 , b, b0 . s −→ h a, bii and t −→ ha0 , b0 i
and a = a0 ∈ A and b = b ∈ B[a/x].
β
β
s = t ∈ A|B iff A|B type and (exists a, a0 .s −→ inl(a) and t −→ inl(a0 ) and a = a0 ∈ A
β
β
or exists b, b0 .s −→ inr(b) and t −→ inr(b0 ) and b = b0 ∈ B).
β
β
s = t ∈ a=b in A iff s −→ axiom and t −→ axiom and a = b ∈ A.
S = T ∈ Ui iff exists A, A0 , B, B 0 , x, x0 .
β
β
β
β
(S −→ x:A→B or S −→ A→B) and (T −→ x0 :A0 →B 0 or T −→ A0 →B 0 )
and A = A0 ∈ Ui and (for all a, a0 . B[a/x] = B 0 [a0 /x0 ] ∈ Ui iff a = a0 ∈ A)
or exists A, A0 , B, B 0 , x, x0 .
β
β
β
β
(S −→ x:A#B or S −→ A#B) and (T −→ x0 :A0 #B 0 or T −→ A0 #B 0 )
and A = A0 ∈ Ui and (for all a, a0 . B[a/x] = B 0 [a0 /x0 ] ∈ Ui iff a = a0 ∈ A)
β
β
or exists A, A0 , B, B 0 . S −→ A|B and T −→ A0 |B 0 and A = A0 ∈ Ui and B = B 0 ∈ Ui
β
β
or exists a, a0 , b, b0 , A, A0 . (S −→ a=b in A) and (T −→ a0 =b0 in A0 )
and A = A0 ∈ Ui and a = a0 ∈ A and b = b0 ∈ A0
β
β
or exists j < i. S −→ Uj and T −→ Uj
x, x0 , y, y 0 range over variables, a, a0 , b, b0 , A, A0 , B, B 0 , s, t, S, T range over possibly open terms, i, j over positive integers.
Figure 4.6: Equality judgements for members of a type
77
4.1. BASIC CONSTRUCTS
such that S = T holds if and only if S = T ∈ Ui for some positive integer i, and s = t ∈ T
holds if and only if axiom ∈ s=t in T .
Proof rules will as far as possible reflect the definitions of the judgements. We will list them
in groups according to the type constructs, each group separated in rules for type formation,
for introducing canonical members, for noncanonical ones, and rules for computation. There
are two versions of each rule for type formation, canonical and noncanonical members, one
for constructing elements as extract terms of proofs and the other one for proving equality of
elements. In the latter case the extract term is always trivial (i.e. axiom) and will be omitted
in our presentation of rules. We will use t in T as an abbreviation for t=t in T .
Universes are given as a cumulative hierarchy as discussed in Section 3.4.6. All type constructors, including Uj for j < i, construct canonical members of some universe Ui. Therefore all
the type formation rules can be viewed as introduction rules for some universe type and are
denoted by the name intro instead of formation. There are no rules for analyzing universes.
A cumulativity rule is important when proving goals like T → U1 in U2 with T being an
element of U1.
Rule Schemes 4.1.6
UNIVERSES
Let i and j are positive integer constants with j < i.
Formation
H ` Ui [ext Uj]
H ` Uj in Ui
by intro universe Uj
by intro
Cumulativity
H ` S=T in Ui by cumulativity at Uj
· H ` S=T in Uj
The type a=b in A mirrors the judgement a = b ∈ A. The rules follow straightforwardly.
Rule Schemes 4.1.7
PROPOSITIONAL EQUALITY
Formation
H ` Ui [ext a=b in A]
· H ` A in Ui
· H ` A [ext a]
· H ` A [ext b]
H ` (a=b in A) in Ui
· H ` A in Ui
· H ` a in A
· H ` b in A
by intro equality A
by intro
Canonical
H ` axiom in (a=b in A)
· H ` a=b in A
H, x:A, H 0 ` x in A
by intro
by intro8
Equality decision
H ` a=b in A by equality
78
CHAPTER 4. THE TYPE THEORY OF NUPRL
Substitution
H ` T [s/x] [ext t] by subst at Ui s=s0 in S over x.T
· H ` s=s0 in S
· H ` T [s0 /x] [ext t]
· H, x:S ` T in Ui
The subst rule allows substituting in a type T a subterm s by another term s0 of equal value
(with respect to the type S), provided the dependency between T and s is known and T
is generally wellformed. The equality rule is a decision procedure that subsumes multiple
application of reflexivity, commutativity, and transitivity rules in a single step. It applies if the
equality of a and b can be deduced from assumptions that are equalities over T (or equalities
over S where S = T is deducible) using only reflexivity, commutativity, and transitivity. The
algorithm behind it and its justification is discussed in Section 5.2.2. Except for the equality
rule there are no rules for analyzing equalities.
Rule Schemes 4.1.8
FUNCTION
Formation
H ` Ui [ext x:S→T ] by intro function S new x
· H ` S in Ui
· H, x:S ` Ui [ext T ]
H ` x:S→T = x0 :S 0 →T 0 in Ui by intro [new y]
· H ` S = S 0 in Ui
· H, y:S ` T [y/x] = T 0 [y/x0 ] in Ui
Canonical
H ` x:S→T [ext λy.b] by intro at Ui [new y]
· H, y:S ` T [y/x] [ext b]
· H ` S in Ui
H ` λz.b = λz 0 .b’ in x:S→T by intro at Ui [new y]
· H, y:S ` b[y/z] = b0 [y/z 0 ] in T [y/x]
· H ` S in Ui
Noncanonical
H, f :(x:S→T ), H 0 ` T [ext t[f (a)/y]] by elim f on a [new y]
· H, f :(x:S→T ), H 0 ` a in S
· H, f :(x:S→T ), H 0 , y:T [a/x], y=f (a) in T [a/x] ` T [ext t]
H ` f (a) = g(b) in T [a/x]
· H ` f = g in x:S→T
· H ` a = b in S
Computation
H ` (λx.b)(a) = t in T
· H ` b[a/x] = t in T
by intro using x:S→T
by reduce 1
9
Equality10
10
This rule is a strengthening of the original one appearing on page 162 of [CAB+ 86] which became necessary
due to the introduction of subset constructors (Section 4.3.5). It also applies to unary equalities. Using this
version of the extensionality rule, it is possible to prove goals such as f :S→T ` f in {x:S|P (x)} →T which
would otherwise not be provable. If the using terms are not supplied, then x:S→T is used.
79
4.1. BASIC CONSTRUCTS
H ` f = g in x:S→T
·
·
·
·
H, y:S `
H ` S in
H ` f in
H ` g in
by extensionality [at Ui]
[using x1 :S1 →T1 , x2 :S2 →T2 ][new y]
f (y) = g(y) in T [y/x]
Ui
x1 :S1 →T1
x2 :S2 →T2
Note, that the elimination rule has to add the term y=f (a) in T [a/x] to the hypotheses
because there might be some other references to f and a in T which are not replaced by
applying this particular rule. The equality y=f (a) in T [a/x] itself will not contribute to the
computational content (extract term) of a proof. Therefore its label, that is the variable of
type y=f (a) in T [a/x] declared in the hypothesis, is superfluous and will be supressed.
The independent function space S→T may be considered as a special instance of x:S→T where
there is no dependency between T and x. Therefore rules for the independent function space
are special versions of the above where all the components indicating the dependency between
T and x are dropped. This causes major simplifications in the following three rules.
Rule Schemes 4.1.9
Formation
H ` Ui [ext S→T ]
· H ` Ui [ext S]
· H ` Ui [ext T ]
INDEPENDENT FUNCTION SPACE
by intro function
H ` S→T = S 0 →T 0 in Ui
· H ` S = S 0 in Ui
· H ` T = T 0 in Ui
by intro
Noncanonical
H, f :S→T , H 0 ` T [ext t[f (a)/y]] by elim f [new y]
· H, f :S→T , H 0 ` S [ext a]
· H, f :S→T , H 0 , y:T ` T [ext t]
For the product type we only give the rules for the dependent version. Rules for the independent
product again follow by a simplification. See [CAB+ 86], page 163 for details.
Rule Schemes 4.1.10
PRODUCT
Formation
H ` Ui [ext x:A#B] by intro product A new x
· H ` A in Ui
· H, x:A ` Ui [ext B]
H ` x:A#B = x0 :A0 #B 0 in Ui by intro [new y]
· H ` A = A0 in Ui
· H, y:A ` B[y/x] = B 0 [y/x0 ] in Ui
Canonical
H ` x:A#B [ext ha, bii] by intro at Ui a [new y]
· H ` a in A
· H ` B[a/x] [ext b]
· H,y:A ` B[y/x] in Ui
80
CHAPTER 4. THE TYPE THEORY OF NUPRL
H ` ha, bii = ha0 , b0 i in x:A#B
· H ` a = a0 in A
· H ` b = b0 in B[a/x]
· H,y:A ` B[y/x] in Ui
by intro at Ui [new y]
Noncanonical
H, p:(x:A#B) H’ ` T [ext spread(p;u,v.t)] by elim p new u,v
· H, p:(x:A#B) H’, u:A, v:B[u/x], p=hhu, vii in x:A#B ` T [hhu, vii/p] [ext
t]
H ` spread(p;u,v.t) = spread(p0 ;u0 ,v 0 .t0 ) in T [p/z]
· H ` p = p0 in x:A#B
· H, a:A, b:B[a/x], p=hha, bii in x:A#B
` t[a, b/u, v] = t0 [a, b/u0 , v 0 ] in T [hha, bii/z]
Computation
H ` spread(hha, bii;u,v.t) = s in T
· H ` t[a, b/u, v] = s in T
by intro [over z.T ]
using x:A#B [new a, b]
by reduce 1
Note, that the elimination rule has to add the term p=hhu, vii in x:A#B to the the hypotheses
list because there might be some other references to p in t which are not replaced by applying
this particular rule.
Rule Schemes 4.1.11
UNION
Formation
H ` Ui [ext A|B] by intro union
· H ` Ui [ext A]
· H ` Ui [ext B]
H ` A|B = A0 |B 0 in Ui
· H ` A = A0 in Ui
· H ` B = B 0 in Ui
Canonical
H ` A|B [ext inl(a)]
· H ` A [ext a]
· H ` B in Ui
H ` A|B [ext inr(b)]
· H ` B [ext b]
· H ` A in Ui
by intro
by intro at Ui left
by intro at Ui right
H ` inl(a) = inl(a0 ) in A|B
· H ` a = a0 in A
· H ` B in Ui
by intro at Ui
H ` inr(b) = inr(b0 ) in A|B
· H ` b = b0 in B
· H ` A in Ui
by intro at Ui
81
4.1. BASIC CONSTRUCTS
Noncanonical
H, d:A|B, H 0 ` T [ext decide(d;a.s;b.t)] by elim d [new a,b]
· H, d:A|B, H 0 , a:A, d=inl(a) in A|B ` T [inl(a)/d] [ext s]
· H, d:A|B, H 0 , b:B, d=inr(b) in A|B ` T [inr(b)/d] [ext t]
H ` decide(d;x.s;y.t) = decide(d0 ;x0 .s0 ;y 0 .t0 ) in T [d/z]
by intro [over z.T ]
using A|B [new a, b]
· H ` d = d0 in A|B
· H, a:A, d=inl(a) in A|B ` s[a/x] = s0 [a/x0 ] in T [inl(a)/z]
· H, b:B, d=inr(b) in A|B ` t[b/y] = t0 [b/y 0 ] in T [inr(b)/d]
Computation
H ` decide(inl(a);x.s;y.t) = r in T
· H ` s[a/x] = r in T
H ` decide(inr(b);x.s;y.t) = r in T
· H ` t[b/y] = r in T
by reduce 1
by reduce 1
In the introduction rules for inl and inr we must guarantee typehood of the whole expression which makes the second subgoal A in Ui (or B in Ui) necessary. In the rules for
decide(d;x.s;y.t) the third subgoal has to be proven even if d is known to evaluate only to
some inl(a).
Some miscellaneous rules are useful for structuring and simplifying proofs. First of all a type
T is inhabited by some x if x is declared as element of T in the hypotheses.
Rule Schemes 4.1.12
HYPOTHESIS
0
0
H, x:T , H ` T [ext x] by hyp x
where T 0 is α-convertible to T
A term T can be proven to be inhabited by some term t by explicitely introducing t and proving
that t is in fact a member of T .
Rule Schemes 4.1.13
EXPLICIT INTRODUCTION
H ` T [ext t] by explicit intro t
· H ` t in T
A proof can be structured by first proving a sequence of internal lemmata which then are used
in the proof. This “rule of consequence” extends to the “cut” rule of ordinary sequent calculus.
Rule Schemes 4.1.14
CUT / CONSEQUENCE
H ` T [ext λx1 .(. . . (λxn .t)(tn ). . . )(tn )] by seq T1 , . . . , Tn [new x1 , . . . , xn ]
· H ` T1 [ext t1 ]
· H, x1 :T1 ` T2 [ext t2 ]
.
.
.
· H, x1 :T1 ,. . . xn :Tn ` T [ext t]
For the sake of legibility superfluous hypotheses may be eliminated. Given a list i1 , . . . , ik
of integers referring to existing hypothesis numbers the thinning rule removes the minimum
number of hypotheses from the original hypotheses list such that the referred-to hypotheses
have been removed and the resulting sequent is closed. The rule fails if no such sequent exists.
82
CHAPTER 4. THE TYPE THEORY OF NUPRL
Rule Schemes 4.1.15
THINNING
H ` T [ext t] by thinning i1 , . . . , ik
· Hj1 ,. . . ,Hjm ` T [ext t]
Judgements about noncanonical terms have been defined by the corresponding judgements on
their values. Therefore it is legal to replace a term T in a goal or in a hypothesis by any other
term T 0 that evaluates to the same value, i.e. to reduce a certain subterm t or to undo reduction
that may have led to it (backward computation). By tagging subterms the computation may
be controlled.
A subterm t of T is tagged by replacing it by [[*;t]] or [[n;t]] where n is a positive integer
indicating the number of reduction steps to be performed (* means “reduce as far as possible”).
11
In the case of backward computation the term that will eventually occur in the subgoal has
to be given in a tagged form.
Rule Schemes 4.1.16
DIRECT COMPUTATION
H ` T [ext t] by compute using S
· H ` T 0 [ext t]
H, x:T , H 0 ` G [ext t] by compute hyp i using S
· H, x:T 0 , H 0 ` G [ext t]
H ` T 0 [ext t] by reverse direct computation using S
· H ` T [ext t]
H, x:T 0 , H 0 ` G [ext t] by reverse direct computation hyp i using S
· H, x:T , H 0 ` G [ext t]
where S is obtained from T by tagging some of its subterms and i refers to the hypothesis
declaring x:T . T 0 is generated by performing computation steps as indicated by the tags.
Exercise 4.1.1
1. Define a boolean type Bool (see Example 3.3.11) with canonical members T and F and a destructor cond(b;s;t). Describe its judgements and appropriate rules.
2. Disjoint union can be viewed as a generalization of the type Bool (see above). Show how to
simulate A|B by dependent products and the type Bool and derive the rules of A|B from those
of Bool and the dependent products.
4.2
Logic in Type Theory
We will now come back to the logical interpretation of types according to line 2 of Table 3.1.
According to the propositions-as-types principle discussed in Section 3.4.4 the type constructors
for (dependent) functions, (dependent) products, and disjoint union allow us to simulate all of
the logical connectives. Thus, if we can provide a type corresponding to logical falsehood, Type
Theory will give us a calculus for dealing with logic for free and thus allow a uniform treatment
of logic and computation.
11
The so-called “tagging restrictions” described on page 172 of [CAB+ 86] have been eliminated, so that all
tags are legal. This extension is justified by a new theoretical result [How89].
4.2. LOGIC IN TYPE THEORY
4.2.1
83
The empty type void
Following the propositions-as-types principle logical falsehood corresponds to the type of all its
proofs, i.e. to a datatype representing the empty set. We will call this type void.
Although propositional equality already gives us the means to express types which we know to
be empty12 there are several reasons to introduce void explicitely.
• The concept of an empty set and logical falsehood is primitive and should be represented
by a type belonging to U1. All simulations are at least of order 2.
• The peculiarities of an empty type need to be made explicit.
• The equality type does not provide noncanonical expressions for analyzing equalities. In
particular there is no way of using the fact that an equality is not true. Adding this to
the equality type would mean the same as introducing void explicitely.
By adding void to Type Theory we are forced to deal with constructs like void#A, void|A,
A→void, and void→A. The first two are simple. Since void has no members void#A must
empty again while void|A essentially is the same as A. But what about A→void? If A is not
empty any function in A→void would introduce a member of void. Therefore A→void must be
empty if A is not. Under the Curry-Howard isomorphism this perfectly fits our understanding
of falsehood; there can be no proof for A ⇒ Λ if A can be proven.
Dealing with void→A is the most complicated case since such a type must be inhabited. This
is the case even if A is empty since, according to our logic, λx.x is of type void→void. But
what shall be the members of void→A in general? Obviously they must be functions, i.e.
expressible as λ-terms λx.b where b evaluates to a member of A if x is instantiated by a term
in void. We know that x cannot be instantiated. Nevertheless on the syntactical level we have
to provide a term as the function’s body. Thus the type void has to come with a noncanonical
form. Since void has no members this form has to create elements of arbitrary types out of no
information, i.e. it must be a member of any type provided we can instantiate its argument
with a member of void.
At a first glance this sounds very strange but we will give a plausibility argument that it does
make sense to introduce a term any(a) which is a member of any type A if a can be instantiated
with a member of void.
In Example 2.6.16 we have argued that assuming T=F where T ≡ λX.λu.λv.u and
F≡ λX.λu.λv.v would cause all λ-terms to be equal. Thus T=F in Bool where
Bool≡X:U1→X→X→X is a meaningful representation of the empty type void. Assuming x to be a member of T=F in Bool we could therefore prove s=t in T for
arbitrary s, t, and T . In particular we could prove A=void in U1 for any type A
and hence the whole type hierarchy collapses.
Essentially this is nothing but another formulation of the logical law that from a proof for
falsehood we may draw any conclusion we want and anything will serve as a proof for that.
In other words, we are justified to make use of the form any(a) since it cannot be instantiated
with a member a of void unless the whole type hierarchy collapses. Thus declaring the function
λx.any(x) to be a member of void→A for arbitrary types A will not be “computational
nonsense”.
12
e.g. A:U1 → (A = A→A in U1)
84
CHAPTER 4. THE TYPE THEORY OF NUPRL
We cannot expect to avoid all complications when adding an empty to the type system. Nevertheless, a theory that shall be used for expressing all of mathematics and programming must
incorporate a notion of falsehood which essentially is the cause for all these complications. The
type void as discussed above seems to be the most appropriate counterpiece to this concept.
Following the spirit of these considerations we extend the type system as follows.
1. The following line will be added to the table of terms (4.2)
canonical, if closed
(types)
noncanonical, if closed
(elements)
void
any(a)
2. Since there are no canonical members of void the term any(a) cannot be reduced. Therefore adding the type void will not change the redex-contracta table (4.3).
3. The type equality judgement “S = T ” (Figure 4.5) will be extended by the case
β
β
“or S −→ void and T −→ void”.
The equality judgement for members of Ui (Figure 4.6) will be extended by the same case.
The equality judgement “not s = t ∈ void” is added to Figure 4.6.
The proof system will is extended by the following refinement rules for void.
Rule Schemes 4.2.1
VOID
Formation
H ` Ui [ext void]
H ` void in Ui
by intro void
by intro
Noncanonical
H, a:void, H 0 ` T [ext any(a)]
by elim a
H ` any(a) in T by intro
· H ` a in void
There is no introduction rule for members of void and no computation rule as well.
As a consequence of adding void there are some complications one should be aware of. Due
to the presence of the elimination rule for void there will be valid proofs of some strange
constructs.
1. “ ` (void→F) in U1” can be proven although F ≡ λX.λu.λv.v is not a type. After the
first introduction step we have x:void ` F in U1 which is accepted by the elimination
rule. As a consequence during the proof one might create garbage in hypotheses lists like
x:void, y:F ` T.
There is no way to get around this. It should be noted, however, that the declaration of
x:void must appear in order to create nonsense like the above. Thus the whole set of
hypotheses is contradictory anyway and it does not hurt to accept any kind of nonsense
as a consequence of something that can definitely not be true.
85
4.2. LOGIC IN TYPE THEORY
2. Using a similar argument we can prove A:U1 ` λh.(λx.x(x))(λx.x(x)) in (void→A).
After the first introduction step we have A:U1,h:void ` (λx.x(x))(λx.x(x)) in A
which again is accepted by the elimination rule.
Strong Normalization has got lost.
However, the term λh.(λx.x(x))(λx.x(x)) already is in normal form and needs no
further reduction. Also function application will not lead to a nonterminating reduction
since the type system accepts (λh.(λx.x(x))(λx.x(x)))(t) only if t can be proven to
be a member of void. Thus h cannot be instantiated.
The lack of strong normalization13 is not particularly due to introducing a noncanonical form
for the type void. The possibility of having types without members alone suffices to prove
that λh.(λx.x(x))(λx.x(x)) is typeable . This was one of the main reasons to use lazy
evaluation in the reduction strategy leading to normalization in a type system that accepts
possibly nonterminating constructs as subterms.
It should also be noted that terms like λh.(λx.x(x))(λx.x(x)) will not occur in a proof unless
they are explicitely introduced. If we would restrict ourselves to terms that are generated as
extract terms we would still have strong normalization.
Exercise 4.2.1 Prove λA.λh.(λx.x(x))(λx.x(x)) in A:U1 → (A=A→A in U1) →A) without using the rules for void.
4.2.2
Constructive logic
We will now have a look at the logical consequences of introducing the type void. Viewing propositions as types as discussed in Section 3.4.4 we can define logical connectives and
quantifiers via definitional equality according to the Curry-Howard Isomorphism.
Definition 4.2.2 Connectives and Quantifiers are defined as logical notations for type
constructs by the following equalities.
A ∧ B
A ∨ B
A ⇒ B
≡ (A)#(B)
≡ (A)|(B)
≡ (A)→(B)
∀x:A.B
∃x:A.B
¬A
≡ (x):(A)→(B)
≡ (x):(A#(B)
≡ (A)→void
As a result of these definitions we get A:U1 ` A ⇒ ¬¬A but the opposite direction is not true:
A:U1 6` ¬¬A ⇒ A. Consequently the law of excluded middle cannot hold (A:U1 6` A ∨ ¬A) and
the logic we have got definitely is not the classical logic. But there is also some other interesting
result. Though not starting with constructive logic we exactly got intuitionistic logic as the
semantics of the formal logic represented by the propositions-as-types principle under the CurryHoward Isomorphism.
Theorem 4.2.3 The propositional logic defined by the “propositions as types” correspondence
is in fact the intuitionistic propositional logic (IPL).
13
in the sense of “any sequence of steps rewriting an arbitrary redex into its contractum is finite”
86
CHAPTER 4. THE TYPE THEORY OF NUPRL
Exercise 4.2.2 Prove that Definition 4.2.2 does in fact define intuitionistic logic.
As a consequence we now may analyze the intuitionistic propositional logic and properties of
the intuitionistic propositional (sequent) calculus (IPC) within Type Theory. Important metatheorems about IPC which had quite complicated proofs will now become astonishingly simple.
We will give two examples.
The cut-rule in sequent calculus (i.e. the seq rule in Type Theory) helps structuring proofs by
lemmata but is a major obstacle to the automation of proofs. It is also a rule that does not
appear in natural deduction and thus an a problem when proving the equivalence of the two
calculi. Cuts can be eliminated from formal proofs at the cost of exponential growth of the
resulting proof. This theorem can be proven in Type Theory by simply using reduction.
Theorem 4.2.4 [Cut elimination]
If H ` G follows from IPC then it also can be shown without cuts
Proof: Look at G as a type. Any proof for G generates a member g of G which essentially
expresses how to prove G. Now normalize14 g to g 0 which is also a proof for G. Since g 0 has
no redices a term (λa.g ∗ )(a), which is generated by the cut-rule can not have appeared in
H ` g0 ∈ G
2
The Cut-elimination theorem makes a proof for the consistency of IPC quite simple. Together
with the completeness of the calculus this means that it is sound, i.e. no theorem which is false
in intuitionistic propositional logic can be proven in IPC.
Theorem 4.2.5
IPC is consistent.
Proof: If IPC would be inconsistent there would be a proof for a theorem and its negation.
By modus ponens we would be able to prove ` Λ. Using Theorem 4.2.4 we could therefore
create a direct proof for ` Λ. Since, however, there is no Λ-introduction rule (i.e. no
introduction rule for void) this is not possible.
2
With similar techniques we also will be able to prove consistency of Gentzen’s sequential calculus
[Gen35].
There is another proof theoretic result which tells us that the introduction and elimination
rules for elimination of canonical members are redundant. Unnecessary detours in a proof, i.e.
introduction of formulae which are eliminated again before being used, can be eliminated. Such
formulae are called maximal.
Definition 4.2.6 A formulae M is called a maximal formula iff it is the conclusion of an
introduction rule and the major premise of an elimination rule.
14
Recall that normalization is possible for terms which are generated.
87
4.2. LOGIC IN TYPE THEORY
Example 4.2.7 A ∧ B is the major premise of the
∧ -intro rule.
Γ, A ∧ B ` C by
· Γ, A, B ` C
∧ -elim
Γ ` A ∧B
· Γ ` A
· Γ ` B
by
∧ -elim
rule and the conclusion of the
∧ -intro
A ⇒ B and A ∨ B are maximal formulae for the same reason.
Theorem 4.2.8 If H ` G follows from IPC then there is a proof without any maximal
formulae in the hypotheses.
Proof:
If we
since
Thus
We only illustrate the key idea:
have A ∧ B in the hypotheses list, then there has been a proof of A ∧ B and therefore,
A ∧ B had to be introduced somewhen, there must be a separate proof of A and B.
the hypothesis A ∧ B may be replaced by the hypotheses A, B.
2
Corollary 4.2.9 If G is provable from H then there is a proof of H ` G which only uses
subformulae of H and G.
The isomorphism between constructive logic and Type Theory is not restricted to first order
logic. Together with the hierarchy of universes the dependent function space allows representing
any higher order quantifier. Thus we also get
• The ω-order functional calculus, where quantification over arbitary functions occurs (as
in ∀f : A→B.T [f ]).
• Any i + 1-order predicate calculus, where quantification over predicate symbols of order i
occurs (as in ∀P : A→Ui.T [P ]).
4.2.3
Classical logic
So far constructive logic. What about “real”, i.e. classical logics? We do not want to lose the
ability of proving “classical” theorems that do not hold true constructively. If we use Gödel’s
translation of classical logic into constructive one we get a solution easily:
Definition 4.2.10 Connectives and Quantifiers for classical logic are defined as abbreviations for type constructs by the following equalities.
¬A
≡ (A)→void
A B
≡ ¬A B
A ∧ B ≡ (A)#(B)
A B
≡ ¬¬A ∧ ¬B)
∀x:A.B ≡ (x):(A)→(B)
x:A.B ≡ (¬(∀x:A.¬B)
Hence classical logic can be expressed in Type Theory as well. The basis of the above representation is the following theorem.
Theorem 4.2.11 Let ◦ denote the Gödel translation from classical logic into constructive logic
and 0 be a translation replacing all the atomic propositional literals A by ¬¬A. If H ` G
follows from the classical Gentzen sequential calculus then (H ◦ )0 ` (G◦ )0 holds true in Type
Theory.
Exercise 4.2.3 Prove that Definition 4.2.10 does in fact define classical logic.
88
4.3
4.3.1
CHAPTER 4. THE TYPE THEORY OF NUPRL
Programming in Type Theory
Proofs as programs
The theory developed so far provides all the constructs we need to express mathematics and
programming. We will now take a closer look at concepts that will support using the theory
efficiently. In particular we will consider the aspect of program development in Type Theory,
knowing that a judgement a ∈ A can be read as “a is a program which meets the specification
A” (c.f. Section 3.4.4). Let us consider an example.
Example 4.3.1 Assume we have constructed a proof for a theorem saying that every natural
number has a integer squareroot:
` ∀x:IN.∃y:IN. (y2 ≤x)
∧
(x<(y+1)2 ).
Then the proof will give us some evidence p that the theorem is true. Instantiating the
definitions of quantifiers we can see that p has the type x:IN → y:IN#((y2 ≤x)#(x<(y+1)2 )).
Thus p must be of the form λx.hhy, pf i where for every x the value y actually is the squareroot
of x and pf is a proof term for that fact. Therefore λx.spread(p(x);y,pf.y) defines a
function computing integer squareroots which is proven correct by the above theorem.
This means: a proof gives us a program for free and thus we can use Type Theory not only for
theorem proving but also for developing programs. In fact one can even prove that theorems
of the kind ∀x:A.∃y:B.P (x,y) lead to the construction of functions from A to B.
Theorem 4.3.2
For each positive integer i the following theorem can be proven in Type Theory.
` ∀A:Ui.∀B:Ui.∀P:A#B→Ui.
∀x:A.∃y:B. P(hhx, yii) ⇒ ∃f:A→B.∀x:A. P(hhx, f(x)ii)
Proof: The formal proof reflects the argument used in the above example. We give a sketch
of it, omitting wellformedness goals:
top
` ∀A,B:U1.∀P:A#B→U1. ∀x:A.∃y:B.P(hhx, yii) ⇒ ∃f:A→B.∀x:A.P(hhx, f(x)ii) by intro (3x)
top 1 1 1
A:U1, B:U1, P:A#B→U1 ` ∀x:A.∃y:B.P(hhx, yii) ⇒ ∃f:A→B.∀x:A.P(hhx, f(x)ii) by intro
new h
top 1 1 1 1
A:U1, B:U1, P:A#B→U1, h:(∀x:A.∃y:B.P(hhx, yii))
` ∃f:A→B.∀x:A.P(hhx, f(x)ii) by intro λx.spread(h(x);y,pf.y)
top 1 1 1 1 1
A:U1, B:U1, P:A#B→U1, h:(∀x:A.∃y:B.P(hhx, yii))
` ∀x:A.P(hhx, (λx.spread(h(x); y, pf.y))(x)ii) by intro
top 1 1 1 1 1 1
A:U1, B:U1, P:A#B→U1, h:(∀x:A.∃y:B.P(hhx, yii)), x:A
` P(hhx, (λx.spread(h(x); y, pf.y))(x)ii) by explicit intro spread(h(x);y,pf.pf)
top 1 1 1 1 1 1 1
4.3. PROGRAMMING IN TYPE THEORY
89
A:U1, B:U1, P:A#B→U1, h:(∀x:A.∃y:B.P(hhx, yii)), x:A
` spread(h(x);y,pf.pf) in P(hhx, (λx.spread(h(x); y, pf.y))(x)ii)
The proof of the last goal is a simple exercise.
2
In Set Theory Theorem 4.3.2 has become known as the axiom of choice. In axiomatizations of
Set Theory (e.g. Zermelo-Fraenkel) there is no proof for it, so it must be taken as an axiom
which, however, is not very easy to justify. In Type Theory, however, we can turn this theorem
into a method for developing programs.
Principle 4
In Type Theory program development is the same as proof construction.
This principle, which has become known under the name “proofs as programs principle” [BC85],
provides a meaningful way to develop programs which are guaranteed to be correct. At a first
glance, programming by proving the satisfiability of a program specification seems to be quite
unnatural and inefficient. However, it has turned out that many program methodologies made
by Hoare [Hoa72], Dijkstra [Dij76], and others are nothing but special reformulations of methodologies for proofs, a fact which was discovered by David Gries [Gri81]. Therefore programming
may be considered to be just a special case of proving theorems and as a result, prescriptions of
proof methodologists like Polya [Pol45] automatically become program methodologies as well.
We will discuss this in further detail after introducing type constructs which are necessary for
“real” mathematics and programming.
4.3.2
Natural numbers
Most of mathematics and programming is based on fundamental arithmetical constructs. We
therefore have to discuss how arithmetic, that is a type of numbers including the concept of
inductive definition, can be handled in Type Theory efficiently.
In the untyped λ-calculus we could simulate numbers by Church Numerals but this would
make even the most primitive concepts very tedious. Therefore we will introduce a concrete
type of numbers and its operations directly. We will first discuss the constructs and rules
that are specific to this type and then turn towards a more practical definition based on these
considerations with a few more operations and rules which are already predefined. 15
The type of natural numbers will be denoted by IN. Following the typical axioms the canonical members of this type are either 0 or generated via the successor function s ∈ IN→IN
from other canonical members. Equality on IN is defined such that s(n)=0 in IN is false
and s(n)=s(m) in IN implies n=m in IN. Natural numbers can be used as arguments of an
expression which represents primitive recursion: ind(x;b;n,F .h) defines a function f with
f (x)=b if x=0, and f (x)=h(n, f (n)) if x=s(n). F is a placeholder for f (n) in the term h. The
semantics of these terms is reflected in the following rules.
15
The arithmetic presented here refers to two conventional arithmetics:
PRA - the Primitive Recursive Arithmetic, and HA - Heyting Arithmetic or Constructive Peano Arithmetic.
90
CHAPTER 4. THE TYPE THEORY OF NUPRL
Rules for IN
Formation
H ` Ui [ext IN]
Canonical
H ` IN [ext 0]
by intro nat
H ` 0 in IN
by intro 0
H ` IN [ext s(n)]
·H ` IN [ext n]
H ` IN in Ui
by intro s
by intro
by intro
H ` s(n)=s(m) in IN
·H ` n=m in IN
by intro
Noncanonical
H, x:IN, H 0 ` T [ext ind(x;b;n,F .h)]
by elim x [new n,F ]
0
·H, x:IN, H ` T [0/x] [ext b]
·H, x:IN, H 0 , n:IN, F :T [n/x] ` T [s(n)/x] [ext h]
H ` ind(x;b;n,F .h) in T [x/z] by intro over z.T [new m,F 0 ]
·H ` x in IN
·H ` b in T [0/z]
·H, m:IN, F 0 :T [m/z] ` h in T [s(m)/z]
Computation
H ` ind(0;b;n,F .h)=t in T
·H ` b=t in T
by reduce 1
H ` ind(s(m);b;n,F .h)=t in T by reduce 1
·H ` h[m,ind(m;b;n,F .h)/n, F ]=t in T
From these rules the whole number theory can be developed. We will only make a few points
about it:
Define x+y ≡ ind(x;y; n,m.s(m)) and then prove that addition is commutative. A proof for
` ∀x:IN.∀y:IN. x+y=y+x in IN turns out to be very tedious because after introducing the
allquantified variables and eliminating y we are left with the subgoals
top 1 1 1 x:IN, y:IN ` x+0=0+x in IN and
top 1 1 2 x:IN, y:IN ` x+s(y)=s(y)+x in IN.
After performing reduction steps (with the definition of + re-instantiated) in both subgoals we
end up with
top 1 1 1 1 x:IN, y:IN ` x+0=x in IN and
top 1 1 2 1 x:IN, y:IN ` x+s(y)=s(y+x) in IN.
Both subgaols need to be proven by something like induction on equalities. For this we need
an induction scheme of the following kind (c.f. Section 2.5.4)
H, x:IN ` P (x) by induction [new n]
·H ` P (0)
·H, n:IN, P (n) ` P (s(n))
where P is a predicate function on integers. Let us complete this rule by adding the evidences
which are constructed by it.
Suppose in the first subgoal we have b as evidence for P (0) being true. Assume v is
a witness for P (n) in the hypotheses of the second subgoal. Then the evidence for
91
4.3. PROGRAMMING IN TYPE THEORY
P (s(n)) will be some term h which depends on n and v. Hence the evidence for P (x)
is built recursively from b and h which fits exactly the semantics of ind(x;b;n,v.h).
The above induction rule therefore is nothing but a special case of the elimination
rule for IN.
Inductive proof and recursive definition become identical in Type Theory, that is they can use
the same form.16 In fact, using the propositions-as-types principle the induction rule can be
viewed as nothing but a special case of the elimination rule for natural numbers, that is the
rule which is dual to the introduction rule for recursively defined expressions.
Although the type IN together with 0,s and ind would be sufficient to express all of arithmetic
it is still impractical. Therefore the type of numbers in NuPRL comes with a lot of expressions
predefined that could have been simulated as well. Natural numbers are extended to integers
(int), canonical numbers 0,1,2,3,. . . are used instead of the lengthy form with the successor
function. Standard operations like the unary - and the binary operations +, -, *, /, mod
and the predicate < are predefined and can be used in infix notation. A form int eq(n;m;s;t)
returns s if n=m in int, otherwise t. less(n;m;s;t) does the same while testing n<m. The
induction form is extended to the negative case.
Exercise 4.3.1 Give proper definitions of difference (x-y), multiplication (x*y), square (x 2 ), integer
division (x/y), quotient remainder (x mod y) and the predicate x<y .
For the NuPRL type of integers the type system is extended as follows:
1. The following line is added to the table of terms (4.2)
canonical, if closed
(types)
int
a<b
noncanonical, if closed
(elements)
n
ind(a;x,y.s;b;u,v.t)
x y x
y
u v u
v
int eq(a;b;s;t) less(a;b;s;t)
-a
a+b
a-b
n ranges over integer constants
a*b
a/b
2. The following line is added to the redex-contracta table (4.3).
16
This was the reason to choose the name ind for recursive definition.
a mod b
92
CHAPTER 4. THE TYPE THEORY OF NUPRL
Redex
Contractum
ind(0;x,y.s;b;u,v.t)
ind(n;x,y.s;b;u,v.t)
b
t[n,ind(n-1;x,y.s;b;u,v.t)/u, v] if n is positive
s[n,ind(n+1;x,y.s;b;u,v.t)/x, y] if n is negative
s if m is n; t otherwise
s if m is less than n; t otherwise
the negation of n
the sum of m and n
the difference of m and n
the product of m and n
0 if n is 0; otherwise the floor of the obvious
rational number
0 if n is 0; otherwise the positive integer nearest 0
that differs from m by a multiple of n
int eq(a;b;s;t)
less(a;b;s;t)
-n
m+n
m-n
m*n
m/n
m mod n
n, m range over integer constants
3. The type equality judgement “S = T ” (Figure 4.5) and the equality judgement for members of Ui (Figure 4.6) are extended by the cases
β
β
or S −→ int and T −→ int
β
β
or exists a, a0 , b, b0 . S −→ a<b and T −→ a0 <b0 and a = a0 ∈ int and b = b0 ∈ int
The following equality judgements for members of int and a<b are added in Figure 4.6.
β
β
s = t ∈ int iff exists n.s −→ n and t −→ n
β
β
s = t ∈ a<b iff s −→ axiom and t −→ axiom
β
β
and exists m, n.a −→ m and b −→ n and m is less than n.
The type of integers comes with many predefined rules. For the sake of legibility we have
written the equality rules in an abbreviated form omitting the second term and the equality
sign. The full form follows by a straightforward extension.17
Rule Schemes 4.3.3
Formation
H ` Ui [ext int]
INTEGERS
by intro int
H ` Ui [ext a<b] by intro less
· H ` int [ext a]
· H ` int [ext b]
H ` int in Ui
H ` a<b in Ui by intro
· H ` a in int
· H ` b in int
Canonical
Let n be an integer constant.
H ` int [ext n] by intro n
H ` n in int
H ` axiom in a<b
· H ` a<b
17
by intro
by intro
For instance, the full form of the formation rule for a<b would be
H ` a<b = a0 <b0 in Ui by intro
· H ` a=a0 in int
· H ` b=b0 in int
by intro
93
4.3. PROGRAMMING IN TYPE THEORY
Noncanonical
Let op be one of +,-,*,/, or mod.
H ` -t in int by intro
· H ` t in int
H ` int [ext m op n]
· H ` int [ext m]
· H ` int [ext n]
by intro op
H ` int eq(a;b;s;t) in T by intro
· H ` a in int
· H ` b in int
· H, a=b in int ` s in T
· H, (a=b in int)→void ` t in T
H, z:int, H 0
· H, z:int,
· H, z:int,
· H, z:int,
H ` m op n in int
· H ` m in int
· H ` n in int
by intro
H ` less(a;b;s;t) in T by intro
· H ` a in int
· H ` b in int
· H, a<b ` s in T
· H, (a<b)→void ` t in T
` T [ext ind(z;x,y.s;b;x,y.t)]
by elim z new x [,y]
0
H , x:int, x<0, y:T [x+1/z] ` T [x/z] [ext s]
H 0 ` T [0/x] [ext b]
H 0 , x:int, 0<x, y:T [x-1/z] ` T [x/z] [ext t]
H ` ind(z;x,y.s;b;u,v.t) in T [z/w] by intro over z.T [new m,h]
· H ` z in int
· H, m:int, m<0, h:T [m+1/w] ` s[m, h/x, y] in T [m/w]
· H ` b in T [0/w]
· H, m:int, 0<m, h:T [m-1/w] ` t[m, h/u, v] in T [m/w]
Computation
H ` ind(z;x,y.s;b;u,v.t)=t0 in T
· H ` b=t0 in T
· H ` z=0 in int
by reduce 1 base
H ` ind(z;x,y.s;b;u,v.t)=t0 in T by reduce 1 down
· H ` s[z,ind(z+1;x,y.s;b;u,v.t)/x, y]=t0 in T
· H ` z<0
H ` ind(z;x,y.s;b;u,v.t)=t0 in T by reduce 1 up
· H ` t[n,ind(n-1;x,y.s;b;u,v.t)/u, v]=t0 in T
· H ` 0<z
Let a and b are canonical int terms.
H ` int eq(a;a;s;t)=t0 in T
· H ` s=t0 in T
by reduce 1
H ` int eq(a;b;s;t)=t0 in T
· H ` t=t0 in T
by reduce 1
(where a 6= b)
H ` less(a;b;s;t) =t0 in T
· H ` s=t0 in T
by reduce 1
(where a is less than b)
H ` less(a;b;s;t) =t0 in T
· H ` t=t0 in T
by reduce 1
(where a is not less than b)
Arithmetic decisions
H ` T
by arith at Ui
94
CHAPTER 4. THE TYPE THEORY OF NUPRL
The arith rule is a decision procedure which is used to justify conclusions which follow from
the hypotheses by a restricted form of arithmetic reasoning. arith can deal with terms denoting arithmetic relations, namely terms of the form t1 ρt2 , where ρ is one of =,6=,<,>,leq,≥18
and t1 , t2 are arithmetic expressions built up by integers and +,-,*,/, mod.
The conclusion T has to be void of of the form G1 | . . . |Gn where each Gi is an arithmetic
relation. If T can be justified then the subgoals of arith are of the form ti in int, where
the ti are the terms occurring on the left- and right-hand side of each Gj . The algorithm
behind arith and its justification is discussed in Section 5.2.1.
H ` T [ext t] by monotonicity i1 op i2
· H, hyps ` T [ext t]
where i1 and i2 are numbers of hypotheses that are arithmetic relations and op is one of +,-,*.
hyps are the additional hypotheses that can be deduced from from op and hypotheses i1 and
i2 using monotonicity rules.19
4.3.3
The NuPRL type of finite lists
NuPRL provides a type of finite lists over elements of an arbitrary type A denoted by A list.
The canonical elements of A list are the empty list nil and a.l, where a is an element of
a and l in A list. Functions on lists are built inductively in terms of a list-induction form
list ind(x;b;y,l,F .h). The meaning of this form is given by the following equations.
list ind(nil;b;y,l,F .h) = b and
list ind(a.r;b;y,l,F .h) = t[a, r,list ind(r;b;y,l,F .h)/y, l, F ].
The definition of natural numbers by 0 and the successor function s may be considered as a
particular instance of lists over a type with only one element. Therefore the rules for lists can
be derived as extensions of those of IN. See page 159 of [CAB+ 86] for details.
4.3.4
A programming example
Having introduced the standard types for programming we will show by a larger example 20 that
programming and mathematical problem solving are in fact closely related and that applying
the “proofs-as-programs” principle is a meaningful way to develop programs. Consider the
following simple but real programming problem.
Given an integer sequence [a1 , a2 , . . . , an ] of length n write a program to find the sum
i=p ai of a consecutive subsequence ap , ap+1 . . . , ap+q that is maximal among all the
sums of consecutive subsequences ai , ai+1 . . . , ai+k .
Pp+q
18
The rule does not make use of definitional equality, so the relations will appear in terms of NuPRL primitives.
a=b is represented by a=b in int, a6=b by (a=b in int)→void, a>b by b<a , a≤b by (b<a)→void, and a≥b
by (a<b)→void.
19
For instance, if i1 refers to t1>t2 and i2 to t3=t4 and op is +, then the new hypotheses are t1+t3≥t2+t4+1
and t1+t4≥t2+t3+1
20
The example goes back to [BC85] where the principle of proofs of programs was first elaborated.
95
4.3. PROGRAMMING IN TYPE THEORY
program maxseg (A:array of integer);
begin
max := 0;
for lower = 1 to n do
for upper = lower to n do begin
sum := 0;
for count = lower to upper do sum := sum+A[count];
if max < sum then max := sum;
end;
return(max);
end.
Figure 4.7: A straightforward solution to find a maximal segment sum
Such consecutive subsequences are called segments and the problem has become known under
the name maximal segment sum. For example, given the sequence [−3, 2, −5, 3, −1, 2] the
maximal segment sum is 4, achieved by the segment [3, −1, 2].
Let us approach the problem systematically. The first task is to make the problem specification
precise in mathematical notation.
“Given a list a of length n find M such that M = max{
Pq
i=p
ai | 1≤p≤q≤n}”
Since the set over which we are computing the maximum is finite the value M can be computed
by brute force; for example, just list all segments, compute their sums and take the largest (see
Figure 4.7). This however is a very inefficient solution since it needs O(n3 ) steps.
Confronted with a problem of the structure “for all n find p such that A(p, n)” there are really
only a few strategies for solving it.
One possibility is that the construction of p and proof of A(p, n) is uniform in n, as in the
example “for all n find p such that p is not divisible by any y ≤ n”. Here we take p = n! + 1
and prove the proposition without regard for the structure of n. The possibilities for such a
uniform analysis depend heavily on which functions are available for building p and the proof
of A(p, n) directly
Another possibility is that we proceed by induction of one form or another on n. This is
suggested whenever the answer p must be built in stages. Still another possibility is to generalize
some property of A(p, n) by adding an extra parameter m and performing induction on m. This
technique which we will use below is called generalization in Polya’s book on mathematical
problem solving [Pol45] while in the context of programming [Gri81, Dij76, Rey81] it is called
weakening.
Quite often the formal specification of the problem already suggests a method for solving it. In
our example induction is suggested because the problem can be solved trivially for sequences
of length one, and it seems likely that we can decide uniformly how to solve it after adding a
single new element to the list.
So suppose the problem has been solved for lists of length n, yielding sum M on the segment
of length p beginning at index i. Suppose now that we add a new element an+1 . Then we have
to consider two (exhaustive) possibilities.
The new maximal sum is the sum of a segment including an+1 .
96
CHAPTER 4. THE TYPE THEORY OF NUPRL
The new maximal sum does not include an+1 .
How can we decide which of the two cases holds? We cannot simply compare M with M + an+1
because M may be the sum of a segment not contiguous with an+1 . In order to compare
correctly we have to know what the largest possible sum of segments containing a n+1 is. If we
call this sum Ln+1 then the new maximum is the maximum of M and Ln+1 .
How do we compute Ln+1 ? Since we proceed inductively we will already know Ln from the
previous step (L1 will be a1 ). Ln+1 will be Ln + an+1 unless Ln is negative, in which case we
know that the maximum segment including an+1 is simply [an+1 ]. So the computation of Ln+1
is max(an+1 , Ln + an+1 ). This analysis tells us precisely how to solve the problem.
How do we express the above proof in Type Theory? Since integers and lists are primitive
data types we cast the problem in these terms. List are naturally built from the head so
it is convenient to recast the argument in terms of adding a new element a0 at the head of
A. It is also convenient to perform the induction on a list directly rather than on its length.
These modifications actually simplify the formal treatment of the problem although one could
as well formalize exactly the original argument. The key argument of the formal proof which
determines the computational part of the resulting algorithm is sketched in Figure 4.8. It uses
the following definitions.
max(a,b)
|A|
hd(A)
tl(A)
A[i]
sum0(i,j,A)
sum(p,q,A)
M = maxseq(A)
L = maxbeg(A)
≡
≡
≡
≡
≡
≡
≡
≡
less(a;b;b;a)
list ind(A;0;a,A’,lg.lg+1)
list ind(A;0;a,A’,hd.a)
list ind(A;nil;a,A’,tl.A’)
hd(ind(i; m;s.s; A; m;s; tl(s))
ind(j;m,s.0; A[i]; m,s.A[i+j]+s)
sum0(p,q-p,A)
(∀p,q:int. 1≤p ∧ p≤q ∧ q≤|A| ⇒ M ≥ sum(p,q,A) )
∧ (∃a,b:int.
M = sum(a,b,A))
≡ (∀q:int. 1≤q ∧ q ≤|A| ⇒ L ≥ sum(1,q,A) )
∧ (∃b:int.
L = sum(1,b,A))
For the arithmetic relations =,6=,<,>,≤,≥ we have used the abbreviations mentioned in the
previous section.
The algorithm extracted from the proof is
λA.list ind(A;hh0,hh0,pf0 ii;
a,A’,M-L-n. spread(M-L-n;Mn,Ln,hh max(Mn, max(a, Ln + a)),hhmax(a, Ln + a)ii, pf ind i))
where pf0 and pfind are subterms proving the correctness of the given solution. An optimized
version would remove those parts because they have no computational meaning. It should be
noted that the algorithm runs in linear time. Thus programming by proving the satisfiability
of a program specification can lead to a solution which is not only guaranteed to be correct but
also much more efficient than the one programmed ad hoc.
4.3.5
Set Types
As we have seen in the above example, a program extracted from a proof may have parts which
never will be used when computing the program since they only prove the correctness of the
result. The reason for this is that the standard interpretation of propositions as types identifies
97
4.3. PROGRAMMING IN TYPE THEORY
` ∀A:int list.∃M:int.∃L:int.
by intro THEN elim A
A:int list ` ∃M:int.∃L:int.
by intro 0 THEN intro 0 ...
1
2
M=maxseq(A)
∧
L=maxbeg(A)
M=maxseq(nil)
∧
L=maxbeg(nil)
A:int list, a:int, A’:int list, Mn:int, Ln:int, Mn=maxseq(A’), Ln=maxbeg(A’)
` ∃M:int.∃L:int.
M=maxseq(a.A’) ∧ L=maxbeg(a.A’)
by intro max(Mn,max(a,Ln+a)) THEN intro max(a,Ln+a)
2 1 A:int list, a:int, A’:int list, Mn:int, Ln:int, Mn=maxseq(A’), Ln=maxbeg(A’)
` max(Mn,max(a,Ln+a))=maxseq(a.A’) ∧ max(a,Ln+a)=maxbeg(a.A’)
by reasoning about lists and arithmetic reasoning
Figure 4.8: Sketch of the final proof
existential quantifiers with products. While for proving correctness of the algorithm (once and
for all) this component may have been necessary it must be considered garbage during the
computation process. We could eliminate it again using the spread construct but it would be
much more efficient to avoid it being inserted into the algorithm in the first place.
A similar problem occurs when we try to restrict the input domain in the specification to a type
which is not predefined. For instance, in order to express the squareroot problem on natural
numbers (Example 4.3.1) we would have to formulate it as
` ∀x:int. 0≤x ⇒ ∃y:int. 0≤y
∧
(y2 ≤x)
∧
(x<(y+1)2 ).
But this would force us to explicitely carry around information which is uninteresting and
makes the true main goal invisible. It is much more desirable to express IN as a subtype of
int and use the original formulation of the theorem. More general, we need a type construct
{x:A|P } which for each type A consists of those elements of A which satisfy a proposition P .
One might try using the product type for that purpose and express, for instance, IN as
x:int#0≤x. But this is not the same as our intuition of subsets. A function f on x:int#0≤x
would have to take pairs hi, pf0≤i i as arguments where i is an integer and pf0≤i a proof that
it is nonnegative. On the other hand this proof will not be used in the computation and f has
to apply the spread operation in order to get rid of it. Thus a user would be burdened with
providing for each input i a proof of 0≤i which then is thrown away again. We should look for
a more elegant concept for expressing subtypes.
These considerations led to the introduction of a subset constructor {x:A|B} which directly
reflects the concept of set comprehension. The members of this type are the members of a of A
such that B[a/x] is inhabited. Equality on {x:A|B} is equality on A restricted to members of
{x:A|B}.21 In contrast to x:A#B the subset constructor is designed such that an element a
of {x:A|B} does not contain a proof for B[a/x] (being inhabited). Thus we know that B[a/x]
holds for a in {x:A|B} but we must not use this information in constructive proofs simply
because a itself does not provide it unless, of course, there is a method of proving B[a/x]
directly from a (as x≥0 can be proven for x=5).
21
There is also an independent version {A|B} which contains the same elements as A if B is inhabited and
is empty otherwise.
98
CHAPTER 4. THE TYPE THEORY OF NUPRL
The difference between these notions becomes more clear in the following example.
Example 4.3.4
Consider the following two types defining integer functions having roots.
F ≡ {f:int→int|∃y:int. f(y)=0} and F’ ≡ f:(int→int)#(∃y:int. f(y)=0)
It is easy to define a function g in F’→int finding the root of each function f p in F (that
is spread(f p;f,p.f(g(f )))=0) simply by pincking the second component of f p which is
the witness for f p having a root. There is no such function h in F→int doing the same for
functions in F because this would require an unbounded search which we cannot express in
the type theory so far.22
To catch the full notion of subsets, however, we should allow knowledge about B[a/x] to be used
in nonconstructive proof parts, that is those which generate axiom as extract term. Therefore,
an elimination rule for a in {x:A|B} will introduce B[a/x] as a so-called hidden assumption
in the hypotheses list. Hidden assumptions, denoted by being enclosed in square brackets, are
hypotheses whose names cannot be used computationally, that is, they cannot be object of an
elimination rule or the hyp rule. These restrictions will only be removed in subgoals of rules
whose the extract terms do not contribute to the extract term of the complete proof as in the
subgoals of all rules which have axiom as extract term.
The extensions due to the subset constructor ar the following ones.
1. The following line is added to the table of terms (4.2)
canonical, if closed
(types)
{x:A|B}
x
x
noncanonical, if closed
(elements)
{A|B}
2. The redex-contracta table (4.3) remains unchanged.
3. The type equality judgement “S = T ” (Figure 4.5) is extended by the case
or exists A, A0 , B, B 0 , x, x0 , a, a0 , u.
β
β
β
β
(S −→ {x:A|B} or S −→ {A|B}) and (T −→ {x0 :A0 |B 0 } or T −→ {A0 |B 0 })
and A = A0 and u occurs neither in B nor B 0
and a ∈ u : A→B[u/x]→B 0 [u/x0 ] and a0 ∈ u : A→B 0 [u/x0 ]→B[u/x]
Correspondingly, the equality judgement for members of Ui in Figure 4.6 is extended by
the case
or exists A, A0 , B, B 0 , x, x0 , a, a0 , u.
β
β
β
β
(S −→ {x:A|B} or S −→ {A|B}) and (T −→ {x0 :A0 |B 0 } or T −→ {A0 |B 0 })
and A = A0 ∈ Ui and ∀b.b ∈ A ⇒ B[b/x] ∈ Ui and ∀b.b ∈ A ⇒ B 0 [b/x0 ] ∈ Ui
and u occurs neither in B nor B 0
and a ∈ u : A→B[u/x]→B 0 [u/x0 ] and a0 ∈ u : A→B 0 [u/x0 ]→B[u/x]
As equality judgement for members of {x:A|B} the following is added in Figure 4.6.
22
In Section 4.4.2 we will introduce the concept of partial functions that will allow us to define h∈F→int
such that f (h(f ))=0 for all f ∈F using an unbounded search. The search is guaranteed to terminate because
of the (nonconstructive) information about f .
4.4. RECURSIVE DEFINITION
99
s = t ∈ {x:A|B} iff {x:A|B} type and s = t ∈ A and exists b.b ∈ B[s/x]
The proof system is extended by the following refinement rules (rules for the independent subset
follow by a simplification).23
Rule Schemes 4.3.5
SET
Formation
H ` Ui [ext {x:A|B}] by intro set A new x
· H ` A in Ui
· H, x:A ` Ui [ext B]
H ` {x:A|B} = {x0 :A0 |B 0 } in Ui by intro [new y]
· H ` A = A0 in Ui
· H, y:A ` B[y/x] = B 0 [y/x0 ] in Ui
Canonical
H ` {x:A|B} [ext a] by intro at Ui a [new y]
· H ` a in A
· H ` B[a/x] [ext b]
· H,y:A ` B[y/x] in Ui
All hidden hypotheses become unhidden in the second subgoal.
H ` a = a0 in {x:A|B} by intro at Ui [new y]
· H ` a = a0 in A
· H ` B[a/x]
· H,y:A ` B[y/x] in Ui
Noncanonical24
H, p:{x:A|B}, H’ ` T [ext t] by elim p
· H, p:A, [B[p/x]], H’ ` T [ext t]
H, p:{x:A|B}, H’ ` T [ext (λy.t)(p)] by elim i new [y]
· H, p:{x:A|B}, H’, y:A, [B[y/x]] ` T [ext t]
Which of the two cases is applied in any instance is determined by whether or not the variable
p of the goal actually appears to the user (as opposed to being generated internally by the
extractor). If it does appear, the first case applies. Otherwise the hypotheses number i has
to be specified. Note that one of the new hypotheses is hidden.
4.4
Recursive Definition
25
For anyone experienced with mathematics or programming recursive definition needs no
motivation; its expressiveness, elegance, and computational efficiency is unsurpassed by any
23
Note the similarity of set and product rules except for the handling of extract terms.
This is a simplification of the elimination rule described in [CAB+ 86]. The well-formedness subgoal has
been removed since it turned out to cause unacceptable practical problems. The equality rule which differed
from being an extension of the introduction rule for the set constructor had to be dropped.
25
This section is not completed yet. So far it gives only a sketchy description how the question of handling
recursive definitions can be answered.
24
100
CHAPTER 4. THE TYPE THEORY OF NUPRL
other construct. The possibility for defining algorithms or mathematical objects by recursive
equations is essential for real mathematics and programming.
In this section we will discuss three extensions of Type Theory by concepts for recursive definitions: an inductive type constructor permitting inductive data types and predicates, a lazy tpe
constructor permitting infinite objects, and a partial function space constructor permitting a
treatment of arbitrary recursively defined functions in an always terminating reduction concept.
Details can be found in [CM85, Men87a, MPC86].
4.4.1
Inductive Types
Inductive definition means interpreting a recursively defined object by the smallest fixed point
of the equation defining it. Nearly all recursive equations are to be understood as inductive
definition. A typical example of an inductively defined type are binary trees over integer
numbers. One of the standard definitions is:
“A tree is either a number n or a tripel hn, t, t0 i where t and t0 are trees and n is a number”.
Thus a type tree representing the binary integer trees has to fulfill the recursive equation
tree = int|int#tree#tree.
We introduce the notation rec(tree. int|int#tree#tree) to describe the type which is defined as the smallest fixed point of the above equation. That is, the rec-constructor does not
provide canonical members on its own but gives us a prescription for constructing members of
the type tree: “To construct a member of tree construct either one of int or an element of
int and a pair of elements of tree.”
The definition of trees over interges can be considered a special instance of trees over an arbitrary
type A. Thus a more general definition should allow defining
tree(A) = A|A#tree#tree.
and instantiating this definition to trees over int. The appropriate NuPRL notation for such
a type is rec(tree,A. A|A#tree#tree; int). It describes a recursive type parameterized by A
and specialized by int.
In Definition 4.1.4 we have defined the judgements of typehood, membership and equality by
mutual induction. Equality of function types x:A→B was defined depending on the notion of
equality of members of the argument type A which depends on the typehood of A and thus
on type equality again. Mutual recursion is also a familiar concept in modern programming
languages: two procedures may call each other several times during execution. Thus it is
desirable to allow recursive types to be mutally recursive.
Therefore, the most general form of defining n mutally recursive types ti parameterized by xi
and instantiated by ai is introducing terms rec(t1 ,x1 .T1 ;. . . ;tn ,xn .Tn ; ti ;ai ) for 1 ≤ i ≤ n.
Any of the xi parameters (and the corresponding instance ai ) can be omitted. The ti are bound
in all the Tj but xi only in Ti .
Recursive types are a manifestation of the basic ideas about recursive data structures (see
[Hoa75] and [GMW79] for a detailed rigorous account) in the setting of Type Theory.
Far more delicate than the above examples is the concept of recursive types when function
101
4.4. RECURSIVE DEFINITION
spaces are involved as in rec(T.T→T) or rec(T.T→A).26
Example 4.4.1 Consider the type S ≡ rec(T.T→int). The recursive equalition S = S→int
gives us a prescription how to build members of S. Any term λx.b in S→int is also a member
of S if b is a term building integers from members of S. So let x be of type S. Then x is also
a member of S→int and thus x(x) ∈ int. As a consequence we would have λx.x(x) ∈ S.
Why does this example cause problems? The combination of the rule for introducing functions
(“to construct a function in A→B assume a member x of A and construct one of B”) and the
rule for introducing members of a recursive type produce a vicious circle. If such a circle occurs
in the definition of a recursive type then the type will contain elements whose computations
fail to terminate. Therefore, it is necessary to give syntactic restrictions on the right hand side
of an equation.
So far the best syntactic restriction on terms occurring in a recursive definition is that in
rec(t,x.T ;a) the variable t may occur only positively in T (which is roughly the same as not
occurring on the left side of an arrow).27
There are no specific canonical forms coming with recursive types since the members are entirely
determined by the right hand side of the equation. However, analyzing the members of a
recursive type provides us with an induction form rec ind(r;x,y.t) which can be viewed as
a generalization of the induction form ind on integers. For the type of binary integer trees
rec(tree. int|int#tree#tree) the following term computes the sum of the values at the
nodes of a tree.
λt.rec ind(t; sum,a-tree.
decide(a-tree;
leaf.leaf;
triple.spread(triple;num,pair.
num+spread(pair;left,right.sum(left)+sum(right)))))
If closed, rec ind(r;x,y.t) is a redex which evaluates to t[λz.rec ind(z; x,y.t), r/x, y].
4.4.2
Recursive functions
In the previous section we have seen that recursive types provide a recursive computation form
rec ind(r;x,y.t) which, as in the case of integers, is the extract term of the elimination rule
for recursive types. As such it denotes a well-defined computable function whose domain is
some recursive type. Quite often, however, we know a recursive solution to a problem without
having an exact recursive description of the domain of application.
Example 4.4.2 The so called 3x+1-function is defined by
0
if x = 1,
if x is even,
f (x) f (x/2)
f (3x + 1) otherwise
26
Such types are legal in languages like Algol or ML but require a notion of partial functions (see Section
4.4.2).
27
See [CM85, Men87a] for a full definition.
102
CHAPTER 4. THE TYPE THEORY OF NUPRL
It could be easily defined as
λx.rec ind(x;f,y.int eq(y;1;0;int eq(y mod 2;0;f(x/2);f(3*x+1))))
and applied although its domain is unknown.
Example 4.4.3 Unbounded search for the root of an arbitrary function could be defined as
λf.rec ind(0;min,y.int eq(f(y);0;y;min(y+1))).
This function is well-defined and terminates for inputs in {f:int→int|∃y:int. f(y)=0}
(c.f. Example 4.3.4) but we have no information about the recursive structure of domain of
the rec ind form.
It is therefore desirable to to provide a concept for representing “all algorithms” in Type
Theory even without knowing the exact domain of application. This would facilitate efficient
programming in Type Theory and explain ordinary programming in it. As a result Type Theory
will not only provide a logically adequate foundation for reasoning about computation but also
a practically adequate foundation in the sense that it can be used as a real programming
language. For this we have to accept algorithms which by their very nature could be partial.
A convenient and natural account of partial functions follows insights from Herbrand [vH67]
which arose from studying algorithms in the context of constructive mathematics and logic.
The key idea is that a computation rule as the reduction rule for rec ind can be understood
and treated as a formal concept before the domain of application can be given. This means
that it can be used to define its domain which depends on what can be proven about it.
Partial functions, therefore, are handled by viewing them as total functions over their domain
of convergence. Following the approach of LCF [GMW79] we denote a partial recursive function
by fix(f ,x.t) where f and x are variables which become bound in the term t.28 Application
is denoted by f [a] to keep a distinction from application in the context of total functions.
fix(f ,x.t)[a] reduces to t[fix(f ,x.t),a/f, x].
Based on this computation rule we know how to say that a fix form converges on an input
a ∈ A to a value b ∈ B. It would be possible to prove fix(f ,x.t)[a] = b in B by a series
of reduction steps. For example we can prove
fix(f,y.int eq(y;1;0;int eq(y mod 2;0;f(x/2);f(3*x+1))))[1] = 0 in int
in two reduction steps. We might prove some other instances of fix(f ,x.t)[a] = b in B
by induction. But we cannot reason about {y:A|fix(f ,x.t)[a] in B}, the exact domain of
convergence, inductively although it has an inductive structure.
In order to provide access to the inductive structure of the domain of partial functions, a
new (noncanonical) form dom(f ) is introduced. If f is in canonical form fix(f ,x.t) then
dom(fix(f ,x.t)) is a redex which reduces to a contractum of the form λx.rec(f 0 ,x.E[t];
fix(f ,x.t); x) where the essential term E[t] is computed by a rather complicated (meta)algorithm.
The contractum cannot be defined as easily as in the other cases since it strongly depends on
the term t used in the function’s body. In the case of the 3x+1 function the algorithm yields
the following domain predicate
28
fix(f ,x.t) can be viewed as extension of λy.rec ind(y;f ,x.t). The most general form of fix again
allows mutal recursion: fix(f1,x1 .t1 ;. . . ;fn ,xn .tn ;fi ).
103
4.5. OTHER TYPES
λn.rec(D,y.
∨
∨
(y=1 in int)
1<y ∧ (y mod 2 = 0 in int)
1<y ∧ (y mod 2 = 1 in int)
∧
∧
D(x/2)
D(3*x+1)
)
For a partial function application f [a] to be sensible one must prove that dom(f )(a) is true.
This will guarantee that the function terminates on the given argument. But the algorithm
given by the term f may also be executed for an element a0 where we cannot prove dom(f )(a0 ).
In these cases the properties of the algorithm are not guaranteed.
The domain predicate allows a proper treatment of partial functions in the frame work of
always terminating computations. A partial recursive function f from A int B actually maps
{x:A|dom(f (x))} into B. It is convenient to collect all the functions mapping a subset of A
into B into a single type which is represented by a new type constructor x:A6→B, denoting the
partial function space.
Contrary to total function spaces partial functions can be used in recursive types without any
restriction. In particular rec(T.T6→T) is a legitimate type and fix(f,x.x[x]) is a member of
it. This function, although an analogue of λx.x(x), is defined only for arguments a which by
themselves are partial functions and satisfy dom(a)(a) such as fix(f,x.x).
4.4.3
Infinite Objects
Besides looking for the smallest solution of a recursive equation we could also search for the
greatest. The equation
tree = int | int#tree#tree
could also be understood as defining finite and infinite binary trees over integers. The concept
of streams, that is infinite sequences of, for instance, character inputs on a computer terminal,
follows the equation
stream = char # stream
where char is a type of single ASCII characters. Such types can be implemented via cyclic
pointer structures which are computed on demand only (lazy types).
In NuPRL they are represented by terms of the form inf(t,x.T ;a) and the rules coming with
these types are in some sense dual to those of the rec type. See [Men87a] for a detailed analysis
of infinite types.
4.5
Other types
In this section we will briefly discuss types not mentioned yet. Details can be found in the
NuPRL-book [CAB+ 86].
104
4.5.1
CHAPTER 4. THE TYPE THEORY OF NUPRL
Quotients
Quotient Types are helpful to define new types from given ones by changing the equality
relation. Rational numbers, for instance, are defined by fractions of integers (c.f. chapter 11
of [CAB+ 86]). Real numbers are constructed by converging sequences of rationals. In these
and similar cases a new equality needs to be defined. Since this kind of equality should not
be treated differently from equality of other types a quotient type construct (x,y):A//E has
been introduced. The members of this type are the elements of A and equality is defined by
the equivalence relation E: s = t ∈(x,y):A//E iff E[s, t/x, y] is satisfied.
4.5.2
Atom
The type atom is provided to model character strings. Its canonical elements are arbitrary
character strings embraced by double quotes. Equality on atoms is decidable. The noncanonical
form atom eq(a;b;s;t) returns s if a=b in atom, and t otherwise. The extensions due to this
type are the following.
105
4.5. OTHER TYPES
1. The following line is added to the table of terms (4.2)
canonical, if closed
(types)
noncanonical, if closed
(elements)
" string"
atom
atom eq(a;b;s;t)
string ranges over character strings
2. The following line is added to the redex-contracta table (4.3).
Redex
Contractum
atom eq(a;b;s;t)
s if a is b; t otherwise
3. The type equality judgement “S = T ” (Figure 4.5) is extended by the case
β
β
or S −→ atom and T −→ atom
The equality judgement for members of Ui in Figure 4.6 is extended by the same case.
As equality judgement for members of void the following is added in Figure 4.6.
β
s = t ∈ atom iff exists string. s −→ string
∧t
β
−→ string
The following refinement rules is added to the proof system
Rule Schemes 4.5.1
ATOM
Formation
H ` Ui [ext atom]
H ` atom in Ui
by intro atom
by intro
Canonical
Let string be a character string.
H ` atom [ext "string"] by intro "string"
H ` "string" in atom
by intro
Noncanonical
H ` atom eq(a;b;s;t) in T by intro
· H ` a in atom
· H ` b in atom
· H, a=b in atom ` s in T
· H, (a=b in atom)→void ` t in T
Computation
Let a and b be different canonical atom terms.
H ` atom eq(a;a;s;t)=t0 in T by reduce 1
· H ` s=t0 in T
H ` atom eq(a;b;s;t)=t0 in T 29
· H ` t=t0 in T
by reduce 1
106
4.6
CHAPTER 4. THE TYPE THEORY OF NUPRL
References and further reading
Most details about the individual type constructs can be found in the book describing the
NuPRL proof development system [CAB+ 86]. Several other books and articles [ML84, NPS90,
BCM88a, BCM88b, Bac89] give introductions to Martin-Löf’s theory of types, on which the
above theory is based.
Semantical questions have been dealt with in [All87a, All87b, Con89, CH90b, Men87a].
The aspect of programming in Type Theory and extracting proofs from programs has been investigated in [BC85, Bac85, Con83, Con84, Con85, Con88, Hay86, Chi87, Smi83, NS84, NPS90,
Lei90].
The concept of recursive types is fairly new. Chapter 12 of [CAB+ 86] and [CM85, CS87, CS88,
Men87a, Men87b, Smi88] present the current research.
Chapter 5
Implementing Automated Reasoning
In the previous chapters we have discussed the development of NuPRL’s type theory out of the
typed λ-calculus. The theory is strong enough to express all of mathematics and programming
and provides everything that is needed for developing formalized proofs “by hand”. The true
practical value of such a formal theory, however, is that its rules show how to reduce semantical
reasoning to syntactical rewriting of sequents, a task which can also be executed by a computer
system. It should therefore be investigated how to provide sufficient machine support for
proving theorems and developing programs in Type Theory efficiently.
One can identify at least three distinct general approaches to automating reasoning.
• At one extreme is pure proof checking, as exemplified by AUTOMATH [Bru80, vBJ77].
These methods rely on a very expressive language to capture the abstractions that make
rigorous mathematics possible. They require large libraries and use a minimum amount
of algorithmic metamathematics. Such techniques are thus very safe but also extremely
tedious and unexciting since the computer only checks that the proof provided by the
user is in fact correct. The level of machine support is extremely low and the loss factor
between formal and ’ordinary’ proofs is very high which makes formal proofs also difficult
to read.
• At the other extreme is automatic theorem proving, as exemplified by various well-known
provers [Ble77, Bib87, BM79, LSBB90, WOLB84]. They rely on Gödel’s completeness
theorem which essentially says that for each theorem that is true a proof can be found by
an exhaustive search procedure. These methods can discover unexpected results but can
also be very costly since in general theorem proving is an undecidable problem.
• In between are approaches which rely to some extent on proof checking and on decision
procedures. They might be characterized as nonheuristic theorem proving since the automatic support is restricted to problems that are quickly recognizable by algorithms.
Decision procedures rely on a deep analysis of theorems and require complex algorithms
whose correctness is a major factor in judging the reliability of a system using them.
Algorithms for simple theories such as equality and arithmetic have been quite successful
and efficient.
The paradigm of tactical theorem proving, first investigated within the LCF Project [GMW79]
offers a method to combine the strengths of all these approaches. The idea was to build a
107
108
CHAPTER 5. IMPLEMENTING AUTOMATED REASONING
system that allows a user to program (safe) extensions of the deductive apparatus and thus to
experiment with a mix of strategies along the spectrum from pure proof checking to full theorem
proving. This can be accomplished by formaling the (informally present) metalanguage of the
underlying theory as an interactive programming language.
During the LCF project this idea resulted in the design of the metalanguage ML which now has
become a widely accepted functional programming language. Experiences with LCF [GMW79],
PL/CV [CJE82], and λ-PRL have shown that implementing a proof system within such a
metalanguage also results in a greater flexibility of the proof system. Since the Edinburgh
LCF approach to automated reasoning was especially compatible with the design principle of
NuPRL and the language ML also strongly reflects the structure of Type Theory the LCF idea
was adopted to the implementation of Type Theory as well.
In this chapter we will discuss the principles of implementing automated reasoning in Type
Theory. We will begin with a description of a flexible, fully interactive system for developing
proofs in Type Theory and then show how to extend its reasoning power by decision procedures
and the paradigm of tactical theorem proving.
5.1
Building systems for interactive proof development
Before we discuss some principles of an implementation we will give a brief summary of the
features of the language ML.
5.1.1
ML
Since the development of ML as the metalanguage for the LCF proof system several dialects
of the language have evolved, including Cambridge ML (of 1985), the implementation of ML
used in NuPRL.1 Three important characteristics make it a good language for our purposes.
• ML is a higher order functional programming language.
• ML has an extensible, polymorphic type discipline with secure types.
• ML has a mechanism for raising and handling exceptions.
In order to understand the principles of an implementation of Type Theory it is not necessary
to know many details of ML. The following summarizes some of the more important, and less
obvious constructs.
Functions are defined in ML using either an abstraction construct as in
let divides = \x.\y.((x/y)*y = x);;
or an equational definition as in
let divides x y = ((x/y)*y = x);;
Both versions define the same function divides which maps integers to functions from integers
to boolean values. \ is an explicit abstraction operator which stands for the more conventional
1
There have been some extensions to specialize the language to NuPRL’s Type Theory. See [GMW79] and
[CAB+ 86], chapters 6, 9, and Appendix A for a complete account.
5.1. BUILDING SYSTEMS FOR INTERACTIVE PROOF DEVELOPMENT
109
λ. The equational form is more general since it can also be used to define functions by recursion
as in
letrec min f start = if
f(start)=0
then start
else min f (start+1)
The function min is a higher order function. It accepts a function f from integers to integers
and maps it into a function from integers to integers. ML allows arbitrary functions to be
arguments of other functions2 as long as they can be typed.
Every value in ML, including functions, is associated with a type. This allows expressing and
enforcing type constraints on the arguments and results of functions. For example, the result
of a function may be forced to be of the type proof. The basic ML data types are tokens,
integers, booleans (tok, int, bool) and a special unit type (written “.” or void) whose only
member is “()”. Tokens are character strings surrounded by back quotes as in ‘PRODUCT‘.
More complex types can be built by means of type constructors →, #, +, list standing for
functions, products, sums (disjoint unions), and lists. There are no dependencies.
A user may extend the type system by assigning names for types built with type constructors
as in
.
lettype intervals = int#int
ML also allows the definition of abstract data types (using abstype, absrectype) which prevent
application programs from accessing the representation of the type directly. Functions that
translate between the new data type and its representation are visible only in the definitions
while other functions on the new type can be used outside. The definition may be recursive.
All the basic types for the NuPRL object language as proof, term, rule (see below) are
defined as abstract types.
The programmer is usually not required to declare types explicitely since the ML system associates a type with every value using Milner’s type-checking algorithm (c.f. Section 3.2.2).
Such a type assignement is polymorphic; a given value may have a number of different types
assigned with it. The degree of freedom depends on the presence of explicit type declarations
in the definition of the object. For instance, the identity function \x.x is associated with the
type *→* where * is a placeholder for types.3 Thus \x.x can be used as identity on any type.
A more interesting example is the typical append function which “glues” two lists together. It
will be assigned the type * list → * list → * list. It can be applied to two lists over
the same type but if we attempt to append a list of integers with a list of tokens then a type
error will result.
ML has a sophisticated exception-handling facility. Certain functions yield runtime errors on
certain arguments and are therefore said to fail on these arguments. A special operator ?
allows to catch failures. The result of evaluating e1 ?e2 where the ei are expressions is the result
of e1 unless a failure is encountered (such as division by 0), in which case it is the result of
evaluating e2 . For instance, the following function returns false if y is zero instead of failing
as the above one.
let divides x y = ((x/y)*y = x) ?
false;;
Exceptions can be raised using the expression fail. The exception-trap mechanism is a convenient way to incorporate backtracking into proof strategies.
2
3
This becomes important when combining predefined tactics into new ones using tacticals (Section 5.3).
It is clear from the context that * does not refer to multiplication at this point.
110
CHAPTER 5. IMPLEMENTING AUTOMATED REASONING
5.1.2
Implementing the object language
The features of ML discusssed above allow an implementation of NuPRL’s object language
which is nearly identical to the definitions given in the previous chapters. One should, however,
keep in mind that there is has to be a distinction between the internal representation of terms,
proofs, rules, etc. and the displayed form. The definition suggests a representation by trees
while a legible display must be text that can be printed as a token. Given the unique grammar
of Type Theory a conversion between the two forms can be done using standard methods.
Proofs
According to definition 3.1.6 proofs are represented as trees where each node represents one
refinement step. A node consists of a sequent, a refinement rule and proofs of the children of
the refinement. A sequent consists of a list of declarations representing the hypotheses and
a term representing the goal (or conclusion) of the sequent. Therefore proofs are recursively
defined as abstract datatypes.
absrectype proof = (declaration list # term) # rule # proof list
Due to the abstract definition a direct access to the components of a proof by the usual ML selectors is prevented. Instead the destructor functions hypotheses, conclusion, refinement,
children have to be used. Proofs can be constructed only by applying rules to a proof goal
using the function refine. Incomplete proofs are proofs which at some leaves have a special
internal rule occuring in the refinement part which is to be replaced by the actual rule if the
proof is continued at that point.
Declarations
A declaration associates a variable with a term. The corresponding datatype representing the
type of NuPRL bindings is a simple product:
abstype declaration = tok # term
A declaration can be built using construct declaration and split into its components via the
ML function destruct declaration.
Terms
The datatype term is a recursively defined abstract datatype mirroring Definition 4.1.1 and its
later extensions. It is a gigantic union of term-constructs following the pattern
term-kind # identifier-list # term-list
where term-kind is a token indicating what kind of term is to be built and identifier-list and
term-list describe how many terms and identifiers are involved.
absrectype term = ‘VOID‘ | ‘UNIVERSE‘#int | ‘FUNCTION‘#tok#term#term . . .
Again the abstract definition prevents a direct access to the components of a term. Instead for
each kind of term there is a constructor and a destructor function like the following ones.
5.1. BUILDING SYSTEMS FOR INTERACTIVE PROOF DEVELOPMENT
111
make void term : term
make function term : tok→term→term→term
make product term : tok→term→term→term
.
.
.
destruct function : term → (tok# (term # term))
destruct product : term → (tok# (term # term))
Besides the internal representation every term has a print representation which is the corresponding NuPRL term enclosed in single quotes as in ’x:int→int’.4 A reasonable print
representation is computed automatically with the execution of a constructor. Thus executing
make function term ‘x‘ ’int’ ’int’ produces the term ’x:int→int’ while the destructor destruct function goes the opposite way. It fails if applied to a term that is not of kind
‘FUNCTION‘. The kind of a term can be determined via the function term kind:term→tok.
If applied to ’x:int→int’ it returns the token ‘FUNCTION‘. The function term to tok maps
each term into its print representation.
Rules
A rule was defined to map a proof goal into a list of subgoals. A proof goal can be viewed as
a degenerate proof without a rule and without children and it would be convenient to think
of rules as mappings from proofs to proofs. However, in order to find out whether a proof
is actually complete, we must also be able to go the opposite way. Each rule must validate
its proof goal provided the subgoals it produces have been validated, that is achieved by a
complete proof. A validation will describe how to combine complete proofs of the subgoals into
a complete proof for the main goal. Thus the actual proof is built by the validation, not by
the rule itself. A validation also includes a method to construct the extract term for the main
goal from those for the subgoals and is therefore necessary if one intends to make use of the
computational contents of a proof.
The idea of validations arose first within the LCF concept of proof tactics [GMW79] and will
be discussed further in Section 5.3 when we investigate programming proofs on the metalevel.
Adopting this concept to the implementation of Type Theory led to viewing a rule as a special
(single step) instance of a tactic. Therefore rules are abstract constructs that are executed by
being mapped into tactics which then actually construct the proof. The representation of Type
Theory in ML is thus contained in the mapping refine from rules to tactics which is described
below. The ML-datatypes of rules, tactics and validations are the following.
abstype rules = . . .
abstype tactic = proof → proof list # validation
abstype validation = proof list → proof
It should be noted that the NuPRL rules like ‘intro at U1‘ do not precisely correspond
to the internal representation of a rule. Strictly speaking the notation intro refers not to
a single rule but to a collection of rules.5 In addition to this ambiguity the various sorts
of rules require different additional arguments like ‘‘at U1’’. Although the context of an
actual proof can be used to disambiguate the name intro during execution there may be
4
5
Note that the quotation marks have to be different from those used for tokens in ML.
The user should not be burdened with more than a hundred individual names.
112
CHAPTER 5. IMPLEMENTING AUTOMATED REASONING
reasons to use individual rules independently of a proof context.6 Therefore internally the
rule constructors are subdivided beyond the ambiguous classes that are normally visible to a
NuPRL user. For instance, there are constructors like function intro, product intro which
are normally designated in proof editing with intro. The function parse rule in context
will convert a token which corresponds to a rule like ‘intro at U1 new y‘ in the context of
a proof with the goal ’x:int→int’ into the actual rule function intro 1 ‘y‘. The same
parser is also used in the proof editor. The function rule to tok maps each rule into its print
representation.
The function refine is the representation of the actual NuPRL logic in ML. It maps a primitive
rule into a tactic which then can be applied to a proof. For instance the deduction of subgoals
of the current proof node when executing refine (function intro 1 ‘y‘) pf (where pf
is a variable of type proof) proceeds according to the following ML algorithm: 7
let H = hypotheses pf
and x,A,B = destruct function (conclusion pf)
in
let H1 = append H (construct declaration ‘y‘ A)
and C1 = substitute [(x,y)] B
and C2 = make equal term [A] (make universe term 1)
in
[ ((H1,C1),,nil); ((H,C2),,nil) ]
;;
That is, on a proof goal of the form H ` x:S→T it creates the subgoals H, y:S ` T [y/x]
and H ` S in U1 which is the same as having executed the rule by intro at U1 new y.
5.1.3
The NuPRL system
So far we have investigated how to implement the individual parts of the NuPRL object language in ML. We will now briefly discuss features of the NuPRL system for interactive proof
development in Type Theory. The reader interested in further details may look up chapters
3-5 and 7 of [CAB+ 86].
The purpose of such a system is developing mathematical knowledge and programs in a style as
it is done in mathematical textbooks. The user will introduce definitions, state formal theorems,
prove them under the control (and with support) of the system, evaluate programs, and store
his results in a library. Therefore the system has the following components.
• A library containing the various user defined objects,
• A definition facility to allow using definitional equalities in objects to make them more
readable,
• A proof editor for claiming theorems and proving them,
• A text editor (which can also handle definitions),
6
A tactic (Section 5.3) defined to introduce all the all-quantified variables, for instance, has to be restricted
to apply introduction on the function space only.
7
is an abbreviation for the internal rule indicating incomplete proofs.
5.1. BUILDING SYSTEMS FOR INTERACTIVE PROOF DEVELOPMENT
113
• An extraction mechanism generating the extract terms of a proof,
• A program evaluator,
• A command interface to create, delete, and manipulate library objects, invoking editors,
It should be mentioned that for the sake of user-friendliness all interaction with NuPRL happens
inside a window. Windows for the command interface and a library display are permanent,
others are dynamically created and deleted as necessary.
The Library
The library may be viewed as a computerized counterpiece of a mathematical textbook. It
contains all the components of a formal theory: theorems, definitions, methods and evaluation
bindings. Each library object comes with a name, a kind, a library position, and a status. These
informations together with a summary description are displayed in the library window.
There are four kinds of objects: THM, DEF, EVAL and ML.
• THM objects contain (incomplete) proofs in the form of proof trees as defined above.
• DEF objects define new notations by definitional equality (a text macro) that can be used
whenever text is edited.
• EVAL objects contain bindings of the form let id = term;; which shall be available when
the evaluator is invoked.
• ML objects contain ML programs that enrich the ML environment. This becomes particularly important when user-defined deduction methods (tactics - Section 5.3) shall be
added.
Every object has associated with it a status, either raw, bad, incomplete or complete (indicated
by ?, -, #, *). A raw object has been changed but not yet checked. A bad object is found
to contain errors. Proofs can be incomplete which means they contain no errors but are not
finished yet. A complete object is checked to be correct and finished.
The position is important since a library will be checked sequentially. All references to other
objects mentioned in an object must be defined, that is the other objects must be positioned
before it.
In the context of the library environment it makes sense to add another expression constructor
and two rules to the type system which refer to existing theorems.
term of(theorem-name)
is a noncanonical NuPRL expression that reduces to the extract term of the THM object theoremname if this is complete. The lemma rule is logically the same as the cut rule seq. A lemma
is stated and proven separately and then used in the hypotheses. The difference is that lemma
refers to a complete proof which is to be found in a separate library object and inserts its
conclusion concl into the hypotheses list.
Rule Schemes 5.1.1
LEMMA
H ` T [ext t[term of(theorem-name)/x]]
· H, x:concl ` T [ext t]
by lemma theorem-name [new x]
114
CHAPTER 5. IMPLEMENTING AUTOMATED REASONING
The def rule provides even more details. It not only adds the conclusion of the theorem
theorem-name but also its extract term ext-term to the list of hypotheses.
Rule Schemes 5.1.2
DEF
H ` T [ext t] by def theorem-name [new x]
· H, x:term of(theorem-name) = ext-term in concl ` T [ext t]
Commands
Commands are used to enter objects in the library, move or delete them, invoke editors, check
definitions, save a session, load back a saved session, invoking ML and EVAL modes, scrolling
the library, etc. For instance, to create a new object of type THM one has to type the command
create theorem1 thm top
The result is that a new raw object of type THM with the name theorem1 is created whose
position is at the top of the library.
create all def before theorem1
creates a raw definition object with the name all positioned immediately before theorem1.
view theorem1 invokes the proof editor on the object theorem1 while view all will invoke
the text editor on all.
The Text Editor
The text editor is the basic tool for communicating with the system when editing objects. It
is used to enter definitions, main goals of theorems, names of rules to be applied to a goal,
etc. Entry of text is restricted to the ASCII characters unless a graphical display and special
fonts are available. 8 Text will be read, parsed and put in the library at the instance the text
window is closed. Besides editing regular text the NuPRL text editor is designed to handle
definitions.
Definitions
The definition facility allows users to define their own notation by definitional equality and
thus extend the formal language according to their needs. The general form of a definition is
new-expression == term
where new-expression may be any text in the alphabet which is available and term is an expression in Type Theory including abbreviations defined so far. The left hand side gives the syntax
of the user-defined notion and the right-hand side its meaning. Formal parameters, which in
the theory have been represented by meta-variables are identified by angle brackets as in
∀<x>:<S>.<P> == <x>:<S>→<T>
A definition may be used whenever text is edited. If, for instance, the above definition has
been stored in the DEF object all it may be invoked from a text editor by typing a special key
8
Therefore >>, ->, == must be used to simulate `, →, ≡.
5.1. BUILDING SYSTEMS FOR INTERACTIVE PROOF DEVELOPMENT
Name of the theorem
Status and Path from the root to here
The goal’s first hypothesis
The conclusion
115
EDIT THM theorem1
# top 1
1. x:int
` ∀y:int. y<y+x*x
The rule
BY intro
The first subgoal together with the
additional hypothesis and its status
1# 2. y:int
` y<y+x*x
The second subgoal and its status
2# ` int in U1
Figure 5.1: A sample Proof Editor Window
and then typing its name all. This will cause the left hand side of the definition to appear
as template ∀<>:<>.<> and the user may enter text into the definition wherever the angle
brackets appear. Entering ‘x‘, ’int’ and ’x=x in int’ will result in ’∀x:int.x=x in int’.
Internally the instantiated definition will be handled as if ’x:int → x=x in int’, that is the
corresponding right-hand side, would have been used. Essentially, the definition mechanism is
managing text macros.
Each parameter on the left hand side of a definition may also include a desciption of what the
parameter shall represent as in
∀<x:var>:<S:type>.<P:prop> == <x>:<S>→<T>.
A description will not influence the meaning of a new notation. It will only affect the template
that appears when invoking the definition which will now contain information on what the user
is expected to enter: ∀<var>:<type>.<prop> . After entering text there will be no difference
to the previous form.
The Proof Editor
The proof editor, or refinement editor, is invoked when a THM object is being viewed. The proof
editor window always displays what is visible from the current node of the proof. When the
editor is first entered the current node is the root of the proof tree. The user may change the
current node by going into subgoals or going to a parent node. Figure 5.1 shows a sample proof
editor window.
A user can use the proof editor to edit the main proof goal and to refine goals by refinement
rules. An intermediate goal can only be modified by changing the refinement rule that has led
to it. Usually the main goal is edited when viewing a theorem for the first time. Then the
display will be
EDIT THM theorem1
? top
<main proof goal>
Selecting the goal field will cause the text editor to be invoked. If the user types
` ∀x:int.∀y:int.
y<y+x*x
116
CHAPTER 5. IMPLEMENTING AUTOMATED REASONING
and closes the text editor again, the input will be checked for syntactical correctness and stored
as main proof goal. The proof will be marked incomplete since no proof step has yet been
executed. 9
EDIT THM theorem1
# top
` ∀x:int.∀y:int.
y<y+x*x
BY <refinement rule>
To refine a goal, a refinement rule must be supplied. This is done by selecting the rule field
and entering a rule in the text editor. If the editor is closed the following steps occur.
1. A global variable prlgoal of type proof is associated with the current sequent. All
subgoals and rules in the proof tree below are ignored.
2. The rule is parsed and applied to prlgoal resulting in a (possibly empty) list of subgoals
and a validation.
3. The validation is applied to the subgoals resulting in a refinement tree of depth 1.
4. The name of the rule is installed as the name of the refinement rule. The refinement tree
produced by the validation is stored in the proof.
5. The proof window is redrawn with new statuses and subgoals.
If the proof rule fails then the refinement is marked as bad and a message displayed in the
command window.
Thus the result of entering intro as refinement rule will be:
EDIT THM theorem1
# top
` ∀x:int.∀y:int.
y<y+x*x
BY intro
1# 1. x:int
` ∀y:int.
y<y+x*x
2# ` int in U1
Term extraction
If a theorem is completely proven its computational content can be extracted recursively from
the proof. Briefly, the extraction form of the top refinement rule becomes the outermost form
of the term being constructed. The parameters of the form then become the terms constructed
from the subgoals generated by the refinement rule. To display the extract term of a theorem
theorem-name one has to evaluate the term term of(theorem-name).
9
If an existing goal is modified then all the proof steps performed before are removed since they may not
apply anymore.
5.2. DECISION PROCEDURES
117
Program evaluation
The NuPRL terms define a functional programming language whose reduction rules have been
discussed in the previous chapter. Besides reasoning about values by using the computation
rules within a proof the NuPRL evaluator gives a user the means to compute the values of terms
and actually use NuPRL to run programs which are either explicitely defined or extracted from
theorems. The evaluation procedure (lazy evaluation) has been presented in Figure 4.4.
5.2
Decision procedures
In mathematical reasoning one quite often encounters problems which in principle are well
explored but whose formal proofs are lengthy and do not yield any computational content. For
such problems the main interest lies in finding out whether it is true or not while the individual
proof steps do not matter. It is, therefore, reasonable to provide fast algorithms which decide
the problem in a way not necessary understandable for the user of a system. These decision
procedures which have to rely on a deep analysis of theorems will from the outside appear as
a single, sophisticated inference rule.
Obviously, such a decision procedure can only be added to the proof system if its consistency
with the rest of the theory can be proven. Since in general Type Theory is undecidable we have
to restrict ourselves to certain subtheories which are known to be decidable and play a major
role in practical mathematical resoning. In this section we will describe decision procedures for
elementary arithmetic and equality reasoning which have been successfully added to the Type
Theory of NuPRL.
5.2.1
arith: a decision procedure for elementary arithmetic
Experience has shown that without a decision procedure for elementary arithmetic one cannot
get very far in practical work with a reasoning system. 10 There are several reasons for that.
1. Arithmetic reasoning appears nearly everywhere.
2. A lot of the arithmetic reasoning is utterly trivial.
3. Results come in an astonishing variety. There are hundreds of lemmata for the same result.
For instance, x+1<y, 0<t ` (x+1)*t < y*t and x<y, 0<t ` x*t < y*t
are syntactically different theorems although the first is a simple variation of the second.
4. A formal arithmetic proof is not always clear, even if it appears to be so. The fact “if
three integers differ at most one from each other then two of them are equal” is intuitively
obvious but has a quite complicated formal proof.
Therefore we have good reasons for handling arithmetic by a decision procedure arith which
from the outside will be viewed as one rule. Of course, before adding such a procedure to the
10
In fact, the LCF project ([GMW79]) got stuck because of that and in the AUTOMATH project([Bru80,
vBJ77]) people spent about 5 years just for proving ring axioms and a few other ones for real numbers simply
because too many proof steps were needed.
118
CHAPTER 5. IMPLEMENTING AUTOMATED REASONING
proof system its theoretical limitations need to be considered and a proof for the correctness of
the resulting procedure has to be given since otherwise we would have no reason to trust in the
mechanical proof. In this section we will give a rather short and informal description. Details
can be found in [CJE82].11
Let us begin with some examples that can be handled by arith and would have been quite
difficult to prove without it. 12
Example 5.2.1 Let i :hyp denote that i is is the number of the hypothesis hyp. Then the
following problems are solved immediately by
i :0<x ` 0<x+2
by arith
i :0<x ` 0<x*x
by arith i * i
i :x+y≤z, j :y≥1 ` x<z
by arith i - j
i :x≤y, j :x6=y ` x<y
by arith
` x-5 < x+10
by arith
i :x<x*x, j :x6=0 ` x≥2 | x<0
by arith i / j
i :x<y, j :0<z ` x*z<y*z
by arith i * i
i :x+y>z, j :2*x≥z ` 3*x+y ≥ 2*z-1
by arith i + i
One should be aware that there are some theoretical limitations for an arith-rule, since not all
arithmetic problems are decidable.
Example 5.2.2 [Hilberts 10th problem]
If f is an arbitrary computable function then there is no way to decide whether f has a root
or not. That is, the problem ∃x1 ,. . . ,xn :int. f(x1 ,. . . ,xn )=0 in int is not decidable. In
fact, even provability of this problem is undecidable.
Therefore we can only expect a to write a decision procedure which is complete for a restricted
arithmetic which handles most of the common problems. Problems involving reasoning outside
of the restricted arithmetic have to be proven by the user or a user-defined strategy (see
Section 5.3). We will therefore define a restricted arithmetic theory (without induction) which
is decidable and then describe a complete decision procedure for it. For simplification we use
quantifier-free arithmetic since all the variables may be assumed to be all-quantified, that is to
be declared as arbitrary variables of type int.
Definition 5.2.3 The restricted arithmetic theory
1. Terms are NuPRL-terms which are built up only from integer constants, variables, and
+, -, *, /, mod.
Atomic formulae are terms of the form t1 ρ t2 where t1 and t2 are terms, and ρ is one of
=,6=,<,>,≤,≥.
Formulae are built up from atomic formulae and the connectives from propositional calculus ∧ , ∨ , ⇒ , ¬
11
The arithmetic decision procedure has first been written for the PL/CV system (1976) and sucessfully been
used in λ-PRL. Its version for NuPRL required some modifications since the previous systems did not use Type
Theory as underlying formalism. The article “An algorithm for checking PL/CV arithmetic inferences” by
Tat-hung Chan in [CJE82] gives a detailed account and a proof of the correctness.
12
It should be noted that all the problems which are proven by the arith procedure could also be proven in
Type Theory directly. Adding arith comes out of purely practical considerations .
5.2. DECISION PROCEDURES
119
2. Equality axioms are the usual axioms for reflexivity, symmetry, and transitivity and a
restricted form of substitution which allows only compound13 substitution. We describe
the axioms by the corresponding rules.
t1 = t2 t1 ρt3
t1 = t2 t3 ρt2
t=u
s=t t=u
t=t
t2 ρt3
t3 ρt1
u=t
s=u
3. Arithmetical axioms are the ordinary axioms of number theory, that is
• Axioms of constant arithmetic like 1+1=2, 2+1=3, 3+1=4, . . . 14
• Ring axioms of the integers and the definition of -. For all integers x,y,z:
(a) x+y=y+x, x*y=y*x
(Commutativity)
(b) (x+y)+z=x+(y+z), (x*y)*z=x*(y*z)
(Associativity)
(c) x*(y+z)=(x*z)+(y*z)
(Distributivity)
(d) x+0=x, x*1=x
(Identities)
(e) x+(-x)=0
(Additive inverse)
(f) x-y=x+(-y)
(Subtraction)
• Axioms of discrete linear order. For all integers x,y,z:
(a) ¬(x<x)
(Irreflexivity)
(b) x<y ∨ x=y ∨ y<x
(Trichotomy)
(c) x<y ∧ y<z ⇒ x<z
(Transitivity)
(d) ¬(x<y ∧ y<x+1)
(Discreteness)
15
• Definitions of order relations and inequality. For all integers x,y,z:
(a) x6=y ⇔ ¬(x=y)
(b) x>y ⇔ y<x
(c) x≤y ⇔ x<y ∨ x=y
(d) x≥y ⇔ y<x ∨ x=y
• Monotonicity Axioms of addition and multiplication. For all integers x,y,z,w:
(a) x≥y ∧ z≥w ⇒ x+z≥y+w
(Addition)
(b) x≥y ∧ z≤w ⇒ x-z≥y-w
(Subtraction)
(c) x≥0 ∧ y≥z ⇒ x*y≥x*z
(Multiplication)
(d) x>0 ∧ x*y≥x*z ⇒ y≥z
(Cancellation / Factoring)
(If z and w are constants, then the monotonicity axioms for addition and subtraction are
called trivial monotonicities.)
It is easy to see that restricted arithmetic is a subcomponent of Type Theory. Furthermore,
since only +, -, * and quantifier-free propositional logic is involved classical and constructive
interpretations of arithmetic formulae become identical. Therefore formulae from the restricted
arithmetic theory can be decided by algorithms. To make such an algorithm reasonably powerful, many variants of the above axioms, including the typical laws of computing with integer
constants, should be directly incorporated into it. These variants, modulo the ring axioms, are
given in the tables of Figure 5.2. The rows and columns of these tables are indexed by term
schemas. Every entry contains the conclusions from the hypotheses corresponding to its row
and column
13
This means that from x=z and x6=x*y one may conclude z6=x*y but not z6=z*y.
Laws like 4+9=13 or 4*9=36 are derived from these by using the ring axioms.
15
These equivalences give rise to the following representations of the order relations in NuPRL. a=b is
represented by a=b in int, a6=b by (a=b in int)→void, a>b by b<a , a≤b by (b<a)→void, and a≥b by
(a<b)→void. The arith procedure accepts the right hand sides as placeholders.
14
120
CHAPTER 5. IMPLEMENTING AUTOMATED REASONING
x>y
z>w
x+z≥y+w+2
x≥y
x+z≥y+w+1
x=y
x6=y
x+z≥y+w+1
y+z≥x+w+1
-----
x>y
z>w
x-w≥y-z+2
x≥y
x-w≥y-z+1
x=y
x-w≥y-z+1
y-w≥x-z+1
-----
x6=y
Addition
z≥w
x+z≥y+w+1
x+w≥y+z+1
x+z≥y+w
x+w≥y+z
x+z≥y+w
y+z≥x+w
-----
z=w
x+z≥y+w+1
z6=w
-----
x+z≥y+w
-----
x>0
x≥0
x=0
x+z=y+w
x+w=y+z
x+z6=y+w
x+w6=y+z
x+z6=y+w
x+w6=y+z
-----
x≤0
x<0
x6=0
Subtraction
z≥w
z=w
x-w≥y-z+1 x-w≥y-z+1
x-z≥y-w+1
x-w≥y-z
x-w≥y-z
x-z≥y-w
x-w≥y-z
x-w=y-z
y-w≥x-z
y-w=x-z
----x-w6=y-z
x-z6=y-w
z6=w
---------
Multiplication using xy for x*y
y≥z
y>z
y=z
y6=z
xy≥xz xy>xz xy=xz xy6=xz
xy≥xz xy≥xz xy=xz ----xy=xz xy=xz xy=xz xy=xz
xy=0
xy=0
xy=0
xy=0
xy≤xz xy≤xz xy=xz ----xy≤xz xy<xz xy=xz xy6=xz
----- xy6=xz xy=xz xy6=xz
Cancellation using xy for x*y
xy>xz xy≥xz xy=xz xy6=xz
x>0 y>z
y≥z
y=z
y6=z
x<0
y<z
y≤z
y=z
y6=z
x6=0 y6=z
----- y=z
y6=z
x-w6=y-z
x-z6=y-w
-----
Figure 5.2: Variants of the basic axioms
Since every formula in restricted arithmetic has an equivalent one in conjunctive normal form
and all conjunctions can be dealt with seperately it is sufficient to have arith deal only with
goals of the form H ` G1 ∨ . . . ∨ Gn where each of the Gi are atomic formulae in restricted
arithmetic. As usual, the case n = 0 means that the conclusion is false, that is void.
We will explain the decision procedure by a running example. Consider the goal
H, i :x+y>z, H 0 , j :2*x≥z, H 00 ` 3*x+y≥2*z-1
The first step of the arithmetic decision procedure is dealing with monotonicities. That is, conclusions which can be derived from the monotonicity axioms will be added as new hypotheses.
Some monotonicity steps which we call trivial monotonicities can be performed automatically
while others need greater care and have to be specified explicitely.
Definition 5.2.4 A trivial application of monotonicity is an application of a monotonicity
axiom for addition with one of the hypotheses given in the form nρm where m and n are
integer constants and ρ is any infix arithmetic relation operator. Any other application of a
monotonicity axiom is called nontrivial
Intuitively, a trivial application of monotonicity corresponds to adding constants on both sides
of a relation in a meaningful way. For instance, we may conclude x+26=y+4 from x=y but we
cannot draw any conclusions about x+2 and y+4 from x6=y.
Example 5.2.5 In our example the monotonicity is nontrivial. We want to add hypotheses i
and j and thus have to call arith i + j. As a result we get according to the addition table.
H, i :x+y>z, H 0 , j :2*x≥z, H 00 , x+y+2*x≥z+z+1 ` 3*x+y≥2*z-1
Since in restricted arithmetic classical and intuitionistic reasoning is the same we are allowed
to choose a negative representation of the problem. That is, we prove that assuming all the
121
5.2. DECISION PROCEDURES
conclusions of the sequent to be false leads to a contradiction. This is a standard trick which
reduces the problem to finding a contradictory conjunction of hypotheses since it is easy to
prove that H ` G1 ∨ . . . ∨ Gn is provable if and only if H, ¬G1 ,. . . ,¬Gn ` false can be
proved. The example sequent thus is modified to
H, x+y>z, H 0 , 2*x≥z, H 00 , x+y+2*x≥z+z+1 ¬(3*x+y≥2*z-1) ` false
In the hypotheses we may safely ignore all those which are not arithmetic formulae since these
will not contribute to a arithmetic solution of the problem. The next step is a normalization
of the comparands in each formula into the standard representation of polynomials by sums
of products a*xn1 *xn2 . . . +. . . . This is a standard arithmetical conversion which obviously does
not affect the truth of the sequentbut causes equal terms to become syntactically identical.
In our example we get
x+y>z, 2*x≥z, 3*x+y≥1+2*z ¬(3*x+y≥(-1)+2*z) ` false
Now all the comparands are transformed into monadic linear polynomials, that is expressions
of the form c + ui where ui is a variable. This means tha all the nonconstant components
are treated as a (possibly new) variable. It can be shown that the resulting comparation is
contradictory if and only if the original one has been. The proof, however, is quite tedious.
In the example we select u0 ≡x+y, u1 ≡2*x, u2 ≡3*x+y, and u3 ≡2*z which results in
u0 >z, u1 ≥z, u2 ≥1+u3 ¬(u2 ≥(-1)+u3 ) ` false
Now all the formulae are converted into the form t1 ≥ t2 where t1 is either 0 or a variable
ui and t2 is a monadic linear polynomial with a nonnegative constant. This can be done by
using conversion tables.16 In our case the result is
u0 ≥z+1, u1 ≥z, u2 ≥1+u3 u3 ≥u2 +2 ` false
Such a form can now be converted into a graph representing the order on the variables. A
2
node represents variables or constants and an edge ui −→ uj indicates ui ≥uj +2. If the
hypotheses are contradictory the graph must have a positive cycle (and vice versa). Whether
the graph has positive cycles or not can be easily decided by a standard algorithm. In the
example the resulting graph is
1
u0
*
z
Y
HH
1
0
HH
HH
u2
u1
-
u3
2
There is a cycle involving u2 and u3 which means that the original sequent is true.
The arith procedure for NuPRL deals also with nonelementary arithmetic expressions, that is
with arithmetic relations whose comparands are build not only from +, -, *. These expressions
are treated as atomic integer terms. arith does not perform any wellformedness proofs and
therefore leaves subgoals of the form t in int where t is a term that cannot be decomposed
any further by splitting additions, subtractions or multiplications. As a convenience, arith
accepts also goals containing terms which are not arithmetic relations. Such terms are simply
16
Typical conversions are ¬x≥y ⇔ x<y, x>y ⇔ x≥y+1, x=y ⇔ x≥y ∧ y≥x,
x6=y ⇔ x≥y+1 ∨ y≥x+1, etc. The last of the equivalences destroys the nice conjunctional form we had before.
Therefore, in the worst case the arith algorithm may have exponential complexity (with respect to the number
of arithmetic relations involved). Since the key application of arith is drawing conclusions from a rather small
number of hypotheses it works very fast in the usual cases.
122
CHAPTER 5. IMPLEMENTING AUTOMATED REASONING
Given a goal of the form H1 , . . . , Hm ` G1 ∨ . . . ∨ Gn (false or void in the case n = 0) the algorithm
for arith i op j (where op is one of +, -, *, /) performs the following steps:
1. According to the requested operation perform monotonicity steps and create new hypotheses as
indicated in the corresponding table for op in Figure 5.2,
2. Modify a sequent A1 , ..., Am ` G1 |...|Gn into A1 , ..., Am , ¬G1 , ..., ¬Gn ` false.
3. Convert all the arithmetic formulae to the form t 1 ≥ t2 .
(If disjunctions occur due to the conversion of an inequality try each case separately until the
following steps lead to a positive answer.)
4. Replace all occurences of terms which are not build from +, -, * by a new variable, replacing
multiple occurrences of the same term by the same variable.
Remove all hypotheses which are not arithmetic relations.
5. Rewrite the comparands in each formula into the standard representation of polynomials.
6. Replace all the comparands by monadic linear polynomials c + u i selecting new variable names,
if necessary. All nonconstant parts are treated as a variable.
7. By addition convert all formulae to the form t 1 ≥t2 where t1 ≡ 0 or t1 ≡ ui and t2 ≡ c or
t2 ≡ ui + c.
8. Convert the whole goal into a graph: Build nodes named 0 for constants and use variable names
c
otherwise. An edge ui −→ uj indicates ui ≥uj +c.
9. By a standard algorithm decide whether the graph has positive cycles or not.
Figure 5.3: The arith algorithm
ignored and left to be proven wellformed in the subgoal. The algorithm behind arith is given
in Figure 5.3.
It should be noted that in the current implementation of NuPRL the first, nontrivial monotonicity step has become a seperate rule monotonicity while arith performs the other steps and
trivial monotonicity operations only.
5.2.2
Equality Reasoning
Reasoning about equalities is the problem of verifying that one equality follows as a consequence
of several other equalities, e.g. that f (f (a, b), b) = a follows from f (a, b) = a or that g(a) = a
follows from ggg(a) = a and ggggg(a) = a. Nearly all the problems occurring in practice,
particularly reasoning about programs and the values computed by them require reasoning
about equalities.
As discussed in Section 2.4.4 equality reasoning essentially involves reflexivity, symmetry, transitivity and substitution rules. But a formal proof using these axioms can become extremely
tedious and since 1954 this particular problem is know to be decidable (see [Ack54]). Therefore
it is reasonable to implement equality reasoning as a decision procedure that subsumes multiple
application of reflexivity, commutativity, and transitivity rules in a single step.
There are several algorithms for dealing with equality. The one we will describe here is based
on work by Greg Nelson and Derek. C. Oppen ([NO79, NO80]) and has been successfully
implemented as equality rule in NuPRL. Its key idea is constructing the congruence closure of
a relation on a graph. This method is not restricted to equality reasoning but can be extended
123
5.2. DECISION PROCEDURES
to reasoning about list structures and similar problems as well. Let us explain the algorithm
by an example.
Example 5.2.6 Show d=e ⇒ a(b(d,f),c) = a(b(e,f),c) where a, b, c, d, e, f are
arbitrary terms.
We represent expressions as trees in the usual way for representing terms and equalities of
expressions as “equality links” between nodes. Proving two expressions to be equal then is
the same as showing that a link between the corresponding top nodes can be constructed.
In the above formula the two expressions have c and f as common nodes while d and e are
linked.
a
b
d
PP
P
Equality link
e
PP
P
a
PP
b
PP
@
PP@
P@
P
@
PP@
PP
@
c
f
The equality link means that d and e can be lumped together which essantially is the same
as changing
b
d
PP
P
Equality link
e
PP
PP
@
PP
@
PP
P
@ e
b
PP
PP
PP
f
into
f
In the next step we look for subtrees in which d and e have been subterms and which are
identical in all the remaining nodes. Between the top nodes of these an equality link can be
constructed. In our example we may link b(d,f) with b(e,f) and continue until we have
linked a(b(d,f),c) with a(b(e,f),c).
Mathematically, constructing links between nodes corresponds to computing the congruence
closure of a relation on a graph.
Definition 5.2.7 Let G = (V, E) be a directed graph with labeled nodes (vertices).
For each vertex v let l(v) denote its label and δ(v) the number of edges leaving v. For
1 ≤ i ≤ δ(v) let v[i] denote the i-th successor of v.17 u is a predecessor of v if v = u[i] for
some i.
Let R be a relation on V . Two vertices are congruent under R if l(u) = l(v), δ(u) = δ(v)
and (u[i], v[i]) ∈ R for all 1 ≤ i ≤ δ(u). R is closed under congruences if for all vertices u
and v which are congruent under R the relation (u, v) ∈ R holds. The congruence closure of
R is the unique minimal extension of R which is an equivalence relation and closed under
congruences.
The algorithm MERGE, shown in Figure 5.4 can be shown to construct the congruence closure
of R ∪ {(u, v)} where R is an arbitrary relation on a graph G which is closed under congruences
and u and v are vertices of G. For the sake of efficiency an equivalence relation is represented
by the corresponding set of equivalence classes.
The following example shows how MERGE operates.
17
Multiple edges are allowed, that is for i 6= j v[i] = v[j] is possible.
124
CHAPTER 5. IMPLEMENTING AUTOMATED REASONING
Given a relation R on a graph G which is closed under congruences and two vertices u and v in G.
1. If the equivalence classes of u and v are identical then return.
2. Let Pu be the set of all predecessors of vertices equivalent to u and P v the set of all predecessors
of vertices equivalent to v.
3. Combine the equivalence classes of u and v (by a link).
4. For each pair (x, y) with x ∈ Pu , y ∈ Pv :
If the equivalence classes of x and y are different and x and y are congruent (that is l(x) = l(y),
δ(x) = δ(y) and the equivalence classes of x[i] and y[i], 1 ≤ i ≤ δ(x) are identical) then MERGE
x with y.
Figure 5.4: The MERGE algorithm
Given hypotheses s1 =t1 ,. . . , sn =tn and a conclusion s=t,
1. construct a graph G which corresponds to the set of all terms in the hypotheses and the conclusion. Let τ (u) be the vertex in G representing u and R be the identity relation on the vertices
of G.
2. For 1 ≤ i ≤ n MERGE τ (si ) with τ (ti )
3. If τ (s) is equivalent to τ (t) then s=t follows from the hypotheses. Otherwise it does not follow.
Figure 5.5: The equality algorithm
Example 5.2.8 We want to compute the closure of ggggg(a) = a and ggg(a) = a.
It suffices to construct a graph for ggggg(a) as on the right. Let R be
(v1 , v6 ) (ggggg(a) = a), u=v3 , v=v6 . v2 and v5 are the predecessors of u
and v. Combining the equivalence classes of u and v constructs the class
{v1 , v3 , v6 }. Since the equivalence classes of the successors of v2 and v5
(that is of u and v) are now identical MERGE is called with v2 and v5 . In
the next step v1 and v4 are investigated while {v2 , v5 } are combined. In
the following step the combination of v1 and v4 yields {v1 , v3 , v4 , v6 } and
v3 is checked to be congruent with v2 (and later v5 ). This calls MERGE
on (v3 ,v2 ) which constructs the equivalence class {v1 , v2 , v3 , v4 , v5 , v6 }.
Since all equivalence classes are now identical the algorithm stops. All
six vertices are equivalent.
g
(v1 )
?
g
(v2 )
?
g
(v3 )
?
g
(v4 )
?
g
(v5 )
?
a
(v6 )
Quantifier free equality reasoning with uninterpreted function symbols can be easily reduced to
the congruence closure problem. To find out whether s=t follows from hypotheses s1 =t1 ,. . . ,
sn =tn it suffices to stepwisely build the congruence closure of the given equalities and then find
out whether s and t are equivalent. The algorithm is described in Figure 5.5.
5.2.3
Other Methods
For classical first order logic there is a rich variety of proof methods which usually code some
complete search strategy (see, for instance [Rob65, And71, Bib87]). Inherent in these methods
is the possibility that the procedure will fail after an investment of considerable resources. Since
5.3. METALEVEL PROGRAMMING
125
the full first order logic is undecidable these methods can aid in the discovery of a proof but
cannot be used as decision procedures except for the case of reasoning without quantifiers.
Usually a decision procedure like arith or equality either succeeds completely or fails. There
is, however, a method to combine decision procedures in a way that they cooperate by exchanging information about all the equalites detected.18 An algorithm which combines decision
procedures for quantifier-free theories into a single decision procedure for their combination is
described in [NO79]. It has been sucessfully used in λ-PRL.
5.2.4
Limitations
In the early λ-PRL which did not have the rich type structure of NuPRL the cooperation of
built-in decision procedures (arith, equality, list-theory etc.) was quite powerful. In
NuPRL, however, some more difficulties arise from the typing problem and therefore only a
few decision procedures can be incorporated into the more general theory.
Therefore there are limitations to the concept of automating reasoning by decision procedures.
There will always be mathematical problems a user may want to reason about which do not
belong to a theory which is decidable.
Furthermore, it would not even make sense to extend a “fixed proof system” by a new decision
procedure anytime a user finds a new type of problems that cannot be handled by the existing
ones. Such a rule would have to be “hacked into the system” by some system programmer and
after a while the system is not intelligible anymore because its original clean structure is lost.
It is also impractial since any new method that is to be added to a system has to be proven
correct before which usually is quite difficult.
Thus decision procedures are helpful only for solving problems of a small number of well known
key theories (like arithmetic) but cannot be considered as a general paradigm for automating
reasoning.
5.3
Metalevel Programming
As we have seen, the concept of “fixed proof systems” whose reasoning power entirely depends
on the mechanisms built in by the system programmer is not flexible enough to deal with
reasoning in all parts of real mathematics and programming. Therefore a system should provide
a mechanism that allows a user to experiment with a various strategies while providing the
greatest possible security against faulty proofs.
This idea first came up in the LCF Project [GMW79] and has been realized by allowing the user
to program proof strategies interactively using the metalanguage ML. Freedom to access the
metalanguage from the NuPRL system gives a lot of power for building terms, manipulating
proofs etc. to the user of a system while the desired security is provided by the abstract
definitions of the key datatypes like proof and rule.
Access to the metalanguage allows planning individual proofs in advance and program them
instead of developing them fully interactively. Furthermore, and this is the really interesting
18
This technique is called equality propagation.
126
CHAPTER 5. IMPLEMENTING AUTOMATED REASONING
aspect of the LCF idea, the user may program simple proof strategies which try to apply several
rules at once and use them for completing those parts of the proof which follow straightforwardly
but are quite tedious because of their length. Such metaprograms (which are called tactics) can
be used to search for proofs, to modify existing ones, to hide uninteresting details, to structure
complex proofs, and - together with the definition mechanism, to extend the formal language
of type theory to user-defined concepts. The paradigm of tactical theorem proving provides a
method to combine the accuracy of a machine with the ingenuity of human professionals which
can turn a simple proof-checker into a powerful tool for proving theorems, generating programs,
and developing formal mathematical theories.
5.3.1
Tactical Theorem proving
The concept of tactics is derived from the idea of heuristic problem solving. This method was
systematized already by the Greeks and is a key element in Polya’s heuristic [Pol45] and also
the basis of the Logic Theorist of Newell, Shaw, and Simon [NSS63]. Here, a problem or goal
is viewed as “a set of possible solutions and a test for verifying whether a given element of this
set is in fact a solution to this problem” ([Min63]). In LCF [GMW79] the latter is expressed
by a notion of achievement between events and goals. Thus “many problem solving situations
can be understood as instances of three notions: goal, event, and achievement.”
Tactics are the result of formalizing the idea of top-down heuristics. A tactic decomposes a
goal G into a finite list of subgoals G1 , . . . , Gn and a validation v. If the events gi achieve the
subgoals Gi then a validation v will build an event g := v(g1 , . . . , gn ) as an event for G.
In our setting we think of G as a theorem and g as its proof, that is the evidence for its truth.
To be more specific, we may identify goals with sequents and events with proofs of sequents.
Proofs are allowed to be partial19 and sequents can be considered as degenerated partial proofs
which leads to the datatypes mentioned in Section 5.1.2. The notion of achievement is quite
simple: we say that a proof p achieves the goal G if the top-level sequent of p is the same as
the top-level sequent of the degenerate proof G.
Thus a tactic completes some portion of a proof and produces subgoals that it was unable
to prove completely and a validation that will take any achievement of those subgoals and
produce an achievement of the original goal. If the validation is applied to achievements that
are complete proofs, then the result of the validation is a complete proof of the main goal.
In particular, if a tactic produces an empty list of subgoals then the validation applied to the
empty list produces a complete proof of the goal.
The advantage of this system becomes apparent when one composes tactics. Since a tactic
produces an explicit list of subgoals another tactic can be applied to each of the subgoals; the
tactics thus decompose goals in a top-down manner. This makes it easy to write specialized
and modular tactics and to write special tacticals for composing tactics.
Tactics are classified in two categories, refinement tactics and transformation tactics.
19
Since tactics shall be invoked in an interactive environment, it is desirable to allow them to succeed even if
they leave some subgoals unproven.
5.3. METALEVEL PROGRAMMING
5.3.2
127
Refinement tactics
Refinement tactics are like derived rules of inference. They are invoked by typing the name of
the tactic where a refinement rule is requested by the proof editor. If the tactic succeeds, then
its name will appear as the refinement rule in the proof. Any subgoals that are not completely
proved will be presented as subgoals of the refinement. As we will describe below, it will have
built a refinement proof which connects the original sequent and the resulting subgoals. This
portion of the proof will be hidden from a user although it is saved for other uses (such as
program extraction). When a refinement tactic is invoked the following steps occur
1. The variable prlgoal is associated with the current sequent. All subgoals and rules in the
proof tree below are ignored.
2. The tactic is applied to prlgoal resulting in a (possibly empty) list of subgoals and a
validation.
3. The validation is applied to the subgoals resulting in a refinement tree.
4. The name of the tactic is installed as the name of the refinement rule. The refinement
tree produced by the validation is stored in the proof. All remaining unproved subgoals
become subgoals of the refinement step.
If the tactic fails then the refinement is marked as bad, precisely as if a primitive rule had
failed. Note that since the actual proof is built by the validation, not by the tactic itself there
is no need to undo the work of a failed tactic.
Example 5.3.1 A typical refinement tactic is a tactic performing a case analysis by first
claiming a disjunction A ∨ B and then proving the goal under either of the tow assumptions.
Thus instead of the two-step proof
H ` T by seq A ∨ B
H ` T by cases A B
1. H ` A ∨ B
1. H ` A ∨ B
one would use
2. H, A ∨ B ` T by elim A ∨ B
2. H, A ` T
2.1. H, A ∨ B, A ` T
3. H, B ` T
2.2. H, A ∨ B, B ` T
The intermediate step is invisible when using the tactic cases.
5.3.3
Transformation tactics
Transformation tactics are used to transform one proof into another. In contrast to refinement
tactics they are allowed to examine the whole subproof below a designated node in the proof
tree. If the transformation succeeds then the result of the tactic replaces the previous subproof.
The name of the tactic will not be included in the proof.
Transformation tactics may be used to complete and expand unfinished proofs, or to produce
new ones which are in some sense analogous to a given proof. When a transformation tactic is
invoked by a special keysequence the following steps occur
1. The variable prlgoal is associated with the proof below, and including the current sequent.
2. The specified tactic is applied to prlgoal resulting in a (possibly empty) list of subgoals
and a validation.
128
CHAPTER 5. IMPLEMENTING AUTOMATED REASONING
3. The validation is applied to the subgoals.
4. The proof resulting form the previous step is grafted into the original
Although in general the result of a transformation tactic will depend upon the result of examining the whole subproof below the current node any refinement tactic may be invoked as a
transformation tactic as well. The main implementation difference between refinement tactics
and transformation tactics is how the result of the tactic is used. In the former, the actual
proof constructed is hidden from the user and only the remaining unproved subgoals are displayed. In the latter, the result is explicitely placed in the proof. Thus applying cases A B
as transformation tactic would result in the original proof including the intermediate step.
Example 5.3.2 A typical transformation tactic application is the pair mark and copy which
can be used to use the same argument at several nodes of a proof without applying external
lemmata. The technique is to save the proof below a proof node in some global variable,
move to a different proof node and then invoke copy to re-execute it resulting in a verbatim
copy of the previous proof at the current node.
NuPRL provides the facility for a distinguished transformation tactic known as the autotactic.
This tactic is invoked automatically on the results of each primitive refinement step. There is a
default autotactic but any other tactic t may be used by executing the function set auto tactic
’t’;;.
5.3.4
Validity
The implementation of proofs as abstract data type ensures that there is only one way to modify
proofs, that is by the function refine which is is the representation of NuPRL’s type theory
in ML. Thus all tactics have to be based on refine which is a very simple way of guaranteeing
that any proof resulting from the application of a tactic is logically correct. In fact, one can
even prove the following theorem.
Theorem 5.3.3
The result of a tactic (either transformation or refinement) is a valid NuPRL-proof.
Therefore a user may extend the deductive apparatus of Type Theory by his own strategies
without having to care about the correctness of these new rules. The fact that any proof built by
user-defined rules in the end has been constructed by primitive inference rules of Type Theory
makes user-extensions automatically consistent with the rest of the theory. This gives a user
nearly complete freedom for experimentation while on the other hand guaranteeing correctness
of the results. Together with the definition facility this allows safe extensions of the semantics
of Type Theory.
5.3.5
Writing tactics
We now examine how simple tactics are written. The basics of all tactics are calls to the
function refine.
129
5.3. METALEVEL PROGRAMMING
• t1 THEN t2 : “apply t2 to all the subgoals resulting from t 1 ”.
(Sequencing of tactics)
t THENL [t1 ; t2 ; ..tn ]: “apply ti to the ith subgoal resulting from t”.
• t1 ORELSE t2 : “apply t1 ; if it fails apply t2 ”.
• REPEAT t: “repeat tactic t until it fails”.
• COMPLETE t: “apply tactic t if it completes the proof”.
• PROGRESS t: “apply tactic t if it makes progress”.
• TRY t: “apply t; if it fails apply IDTAC”
Figure 5.6: Important predefined tacticals
Example 5.3.4 Assume we already have written a function new id: proof→tok which for
each proof computes a new identifier which did not occur in the hypotheses yet. Then the
following tactic performs first-order introduction for function spaces x:S→T while automatically supplying a new identifier if necessary.
let f1 intro proof = refine (function intro 1 (new id proof)) proof;;
To combine simple tactics like the above into more sophisticated ones a user does not have
to go into the details of ML. Instead, he may make use of tools called tacticals which are ML
functions that map tactics into tactics. Figure 5.6 lists a few predefined ones20 which have
proven particularly helpful for creating tactics.
Let us explain their usage by some examples.
Example 5.3.5 The tactic cases described above can be implemented as follows.
let cases c1 c2 =
refine( seq [make union term c1 c2] [‘nil‘])
THENL
[IDTAC
;\pf.(
refine (union elim (length (hypotheses pf)) ‘nil‘ ‘nil‘)
THEN refine (thinning (length (hypotheses pf)) )
) pf
]
;;
The first refine will execute the seq rule. The ‘nil‘ indicates that no new variable name
will be given to the new hypothesis. The list of tactics listed after THENL is applied to the
two subgoals of apllying this rule. The first will remain unchanged (IDTAC) while in the
second case union elim is applied to the new hypothesis, that is the last hypothesis of the
resulting subgoal. Afterwards the now superfluous disjunction is removed from the hypotheses
by thinning.
20
IDTAC is a tactic that essentially performs no operation.
130
CHAPTER 5. IMPLEMENTING AUTOMATED REASONING
The tactical REPEAT causes a tactic to be applied to a proof goal and then to the children
produced by it until it fails. REPEAT will catch all failures of the argument tactic and cannot
generate a failure. For example
let repeat intro = REPEAT (refine (parse rule in context ’intro’));;
will perform simple introduction on the proof until it no longer applies. By this all the allquantified variables of a formula are moved to the hypotheses list.
The ORELSE tactical is used if one does not want to care about the exact tactic which has to
be applied. If one tactic fails the given alternative is executed.
Example 5.3.6 The tactic hypothesis checks whether a goal is known because it appears in
the hypotheses. This is done by trying to apply the hyp rule to all the hypotheses of a proof.
letrec hypothesis proof =
let n = length (hypotheses proof)
in
let try hyp no =
if no<=n then refine (hyp no) ORELSE try hyp (no+1)
in try hyp 1
;;
else IDTAC
With the above tactic we can easily define a tactic that performs several alternatives of trivial
immediate reasoning:
let trivial = hypothesis ORELSE (refine (arith 1)) ORELSE (refine equality);;
Just with these tacticals, refine, the NuPRL rules, and some predefined tactics a user can
write remarkably powerful tactics. A very interesting one of this kind is a tactic performing
“immediate” reasoning which is extremely helpful if one does not want to do all the boring
proofs of easy facts. Its construction also shows how to set priorities on the tactics applied in
a heuristic mechanism. The priorities in this case are calculated through sorting by the costs
of their application.
Example 5.3.7 Assume, we have written the following tactics (similarly to hypothesis)
void elim - “Try to find inconsistent hypotheses”
and elim - “Split conjunctions in a hypothesis into components”
imp all intro - “Introduce implications or all-quantifiers”
and intro - “Prove each conjunct separately”
imp elim - “Prove by modus ponens”
or elim - “prove by considering each case individually”.
Then a tactic for immediate reasoning can be defined as follows.
let immediate =
REPEAT
(
hypothesis
ORELSE void elim
ORELSE refine (arith 1)
ORELSE refine (equality)
ORELSE and elim
5.3. METALEVEL PROGRAMMING
ORELSE
ORELSE
ORELSE
ORELSE
) ;;
131
imp all intro
and intro
imp elim
or elim
The first four tactics either fail or succeed without leaving subgoals and may therefore be
considered cheap. The last ones have relatively high costs because they could go wrong
directions in a proof. Tactics like quantifier-elimination could have been included but are not
in this particular tactics.
Occasionally it is desirable to require a tactic to completely prove a goal or to make some
progress towards proving it. Tactics with these properties may be implemented using COMPLETE
and PROGRESS. If tac is a tactic then COMPLETE tac is a tactic that will either completely
prove the goal or fail and PROGRESS tac fails unless the argument tactic performed at least one
refinement step.
The tactical TRY catches every failure of a tactics and executes a no-operattion step instead.
This is particularly useful in combination with THEN if a failing followup tactic should not cause
the whole tactic to fail.
To illustrate the use of transformation tactics we examine a pair of tactics mark and copy that
can be used to copy proofs.
Example 5.3.8 The mark tactic saves a verbatim copy of the given proof in a reference variable
saved proof while copy recursively traverses the saved proof and refines the actual proof
by using the refinement rule of the saved proof. Since this will fail if the saved proof is
incomplete a predicate is refined is defined which causes a stop where no further refinement
rule has been provided.
letref saved proof = void goal proof;;
let mark goal proof =
(saved proof := copy proof goal proof; IDTAC goal proof);;
letrec copy pattern pattern goal =
if is refined pattern
then TRY
(refine (refinement pattern)
THENL (map copy pattern (children pattern))
) goal
else IDTAC goal;;
let copy goal proof = copy pattern saved proof goal proof;;
5.3.6
Experiences.
The tactic mechanism has proved very successful for a broad class of very simple proof techniques. A number of users have written several small special purpose tactics and a variety
of general tactics such as those discussed above (See, most of all [How88a]). These general
tactics have allowed to achieve in a matter of days most of the capabilities of the mechanisms
132
CHAPTER 5. IMPLEMENTING AUTOMATED REASONING
in earlier systems (e.g. PL/CV [CJE82]) which had to be hand coded (on a scale of weeks).
Moreover, these tactics are much easier understood in detail and can be employed in building
more complicated tactics.
The tactic mechanism also allows to structure the deductive power of the system around specialized reasoners. Users have been able to write a collection of tactics and theorems designed to
construct proofs about a particular concept (see, for instance [How86, How87, How88a, Kre86,
Bas89]) Experiences with tactics have demonstrated the effectiveness of the tactic mechanism.
Tactics provide a level of abstraction comparable to that of the object theory. Thus users can
build proofs and tactics with nearly equal facility.
There is an open end to the ideas one might program but this we leave to the users of NuPRL.
However, one should resist the temptation of trying to write tactics whose task is doing all
the proof labour. This would have the same effect as attempting to write a complete Theorem
Prover for Type Theory. Such tactics are usually inintellegible and difficult to control. They
may go wrong paths in the proofs, and make them much bigger than they should be. It
is rather advisable to write small and controllable tactics which are fast and powerful for a
special purpose and are initiated by a user at the right position in a proof.
5.4
References and further reading
The book describing the NuPRL proof development system [CAB+ 86] should be considered as
a reference book for this chapter.
Futher informations about decision procedures can be found in [CJE82] (particularly the Appendix “An algorithm for checking PL/CV arithmetic inferences” by Tat-hung Chan) and
[NO79, NO80].
The concept of tactical theorem proving has been first discussed in [GMW79] and been elaborated for Type Theory in [CKB85]. Tactical theorem proving is also used in Cambridge LCF
[Pau87], λ-PROLOG [FM88], the Oyster system [Bun89], and the KIV system [HRS90].
Chapter 6
Building Theories
We have discussed the theory in which to express mathematics and programming and concepts
for efficient proofs and program development. We will now investigate aspects of “implementing
mathematics”, i.e. developing object theories in a system that implements Type Theory. For
that we need to discuss how to systematically develop theories with a system such that they
are understandable for humans as well.
Applications are very important because they give a lot of insights into the problems that
need to be solved in order to make a proof development system useful. In this section we
will discuss problems and methodologies arising from experiments with the implementation of
mathematical theories with Type Theory.
6.1
Methodology
Auch Polya etc...
Proof Methodology, building libraries, NuPRL Buch ch.10 mit verweisen
math theories (Basin...)
hier vor allem aus Basin + Beispiele Entsprechend meinen Habil ch. 3 Beispielen vorgehen
axiomatisch + extrakt aus modellierungstheorem.
+ using conventions
Conventions for faster search/access
Define objects by theorems with trailing underscores. Use type object for polymorphic definitions.
DEF name,
A formal theory1 consists of a signature Σ = (S, Ω) where S is a set of names for datatypes
and Ω is a family of sets of operation names indexed by arity and result type {Ωdom,range |dom ∈
S ∗ &range ∈ S}. A theory presentation is a pair (Σ, Φ) where Σ is a signature giving the
vocabulary of the theory and Φ is a set of axioms for the theory.
A concrete theory presentation can have the following components:
1
taken from [BG90] and the quoted standard books
133
134
CHAPTER 6. BUILDING THEORIES
• A name used to identify the theory
• A list of names of imported theories, i.e. theories where the new theory depends on.
• A list of type variables involved. We use greek letters α, β, γ to range over type variables.
• A list of new types and type constructors in terms of the type variables (e.g. Set(α).
• A list of operation signatures on the types involved (e.g. ∅:Set(α), ∈:α × Set(α)).
• A collection of axiom schemata for the theory.
• A list of operation signatures which are constructors for a new type. A list of constructors
op1 , ..opn for a new type τ essentially states that all information about operations on τ is
finitely constructible from op1 , ..opn . In particular they introduce induction schemes for
predicates on τ like the following:
∀ P:PROP(τ ). (∀op ∈ {op1 , ..opn }. ∀ x:domain(op). P(x|τ ) ⇒ P(op(x))) ⇒ (∀ y:τ .P(y))
and similarly a scheme for the existence of functions defined by structural induction on τ .
By these a theory is uniquely determined.
introduces
For such such a theory presentation to be represented in NuPRL we need to perform the
following steps:
• Have all imported theories available. This is an operation on the meta-level of NuPRL.
• Prove a metatheorem about the existence of a type theoretical model of the theory. The
typical form would be:
Theorem Model-<name>
∀<type variables involved>:TYPES.
∃<names for new types>:TYPES
∃<names for operations and their typings>
<axioms for the theory>
<induction schemes introduced by the list of constructors>
• Give a series of definitions extracting the newly defined concepts from the theorem (projecting from term of(Model-<name)) and giving the appropriate names to them.
∅:α term of(MODEL-set)(α)2
Note that all the type-variables have to appear in a correct definition because the new
concepts depend on them.
Note that a proof for the theorem Model-<name> is also a proof for the consistency of the new
theory. In the proof we have to give a concrete model for the theory (e.g. simulate finite sets by
finite lists) but due to the open-ended semantics of NuPRL we may use the new concepts as if
they would be NuPRL-primitives. Note also giving a model for a new datatype automatically
135
6.2. SIMPLE THEORIES
induces an equality on the type which satisfies the typical equivalence and substitution axioms.
Thus these axioms need not to be mentioned in the axioms of the theory explicitely.
Given all the informations of a theory presentation all the above steps - except for the creation
of induction schemes from the list of constructors - can be automated. Thus introducing a new
theory can be represented as an ML-object of the NuPRL library (an object of the meta-level
of NuPRL) which loads the theories to be imported, creates an unproven theorem and the
appropriate definitions. We are left with only the proof.
For a more intuitive presentation we will describe this object using the following notation.
¡Name¿ ¡Imported theories¿ ¡Type variables¿ ¡New types¿ ¡New operations¿ ¡Axiom
schemata¿ ¡Induction schemes¿
Theorem MODEL-<Name>
Theory <Name> has a NuPRL model
Proof: Give a model and prove the axioms
2
Definition [Theory of <name>]
A series of definitions giving appropriate notation for using the newly defined concepts.
[THEORY DEVELOPMENT <name>]
The development part of the theory: a sequence of definitions and theorems using
only operations declared within the theory or from imported ones.
In particular theorems about finite constructability of the new types from the constructor operators are important.
6.2
Simple Theories
6.2.1
Elementary logic
c.f. section 4.2
6.2.2
Finite sets
6.2.3
Number Theory
6.2.4
Strings
6.2.5
Finite Automata
6.2.6
Real numbers
Auch zuerst die axiome geben: Peano (imported from IN), Körper, limes dann modellieren.
136
6.3
CHAPTER 6. BUILDING THEORIES
Automated Theorem Proving
[CH90a]
6.4
6.4.1
Application to Program Construction/Development
and verification
program synthesis, verification,...
KIDS, LOPS,...
6.5
References and further reading
Chapter 7
Advanced Topics
There are still a lot of issues about NuPRL which will be the research topics for the next years:
1. How to compute well?
2. How to program well?
3. How to automate typechecking?
This is mainly an issue of automated theorem proving.
4. How to prove theorems efficiently in NuPRL?
This might also be stated as “How to automate reasoning?” and we will discuss this issue
in the following.
7.1
Metamathematics
7.1.1
Expressing meta-concepts in the object language
Motivate: metareasoning macht beweise kürzer möchten wir gerne ermöglichen, also über terme
reden (rekursiv) Diese Idee kann auf teile der ITT angewandt werden und FOL aber schwerlich
auf die ganze (see ch.8). In jedem fall brauchen wir es aber.
But at least we are able to map ML into NuPRL so far that term and proof can be reflected
which means that we can argue about tactics from within NuPRL itself. We could prove results
like
∗: “if P (proof ) then t: tactic succeeds”
and create new rules of inference like
H ` proof by tactic t
1.H ` P (proof )
2.H ` ∗
See the Ph.D. Thesis of Todd Knoblock [Kno87] for more details.
137
138
CHAPTER 7. ADVANCED TOPICS
Experience shows that there is a lot of metareasoning1 in usual mathematical proofs which is
not as easy in formal proof systems.
Example 7.1.1 In a proof of (∃x : A.B)|(∃x : A.C) ` (∃x : A.B|C) one would eliminate
the hypothesis resulting in
(∃x : A.B) ` (∃x : A.B|C)
(∃x : A.C) ` (∃x : A.B|C)
and then have to do “the same” subproof twice. A less formal proof could argue that the
subgoals are practically identical and thus avoid double work.
Can we capture this in tactics? Formulated as a metatheorem this would be:
“If a tactic t proves g(s) then the tactic f (t) proves g(h(s))”.
e.g. if t proves x : A, B ` (∃x : A.B|C)
then f (t) shall prove x : A, C ` (∃x : A.B|C)
The consideration is to prove a goal now just by stating “by tactic f (t)” without actually having
to run the tactic f (t) which might be very time consuming. But how would we do this? In
today’s NuPRL there is no way to do so2 . However, ML and NuPRL resemble each other
strongly and one could think of putting the metalanguage into the object theory. Because of
Gödel’s incompleteness theorem, of course, this is not completely possible but at least a big deal
could be achieved. If one provides term and proof as NuPRL types then a lot of metareasoning
could be done. Before doing so, we have to solve the question of recursive types and partial
functions. Both of them are very difficult and not quite solved yet. Particularly expressing
partial functions in an always terminating reduction concept is extremely complicated.
In the following we sketch some ideas and the current NuPRL solution
[CH90a]
7.1.2
Reflection
[ACHA90, GS89]
7.2
Alternative theories (optional)
Since the introduction of dependent types in many of the rules defined so far we are forced to
specify the exact universe. This is particularly annoying when trying to model set theoretic
notions. For instance, subsets of a set A can not always be defined via p : A→U1 3 since also
concepts from U2 , i.e. properties of propositions may play a role in their definition. So we
would have to express a whole powerset hierarchy P owj (A)4 . Therefore, the question arises if
we could drop the distinction between universes and just have one universe type U . This would
make things a lot easier.
1
i.e. reasoning about proofs and proof methods
But see [KC86a, KC86b] for recent work intended to change this
3
see Section ??
4
This is mainly a problem caused by defining sets. Function types do not need a hierarchy like (IN→IN) 2 in
their definition
2
7.3. HOW TO COMPUTE WELL?
7.2.1
Girard’s Theory
7.2.2
The calculus of constructions
139
[CH85, CH88, Coq90]CoquandHuet in VL einfließen lassen als Konkurrenz, intro o.ä. wegen
der vielen guten eigenschaften. KOntexte etc.
7.2.3
Other Type theoretic calculi
[AC90, Ber68, Sup72]
7.3
How to compute well?
This means better evaluators, compilers for Type Theory, faster computation
For λ-PRL, a previous version, there are already some studies by Jim Sasaki [Sas85]. Very
helpful are also
• A study of functional programming in general [Car84] from which we may import technologies
• procedural components to be added to NuPRL
This would help making NuPRL as effective as other programming languages which means it
might compete with “real” languages.
7.4
References and further reading
a fairly new subject, Weyhrauch
[AL84, ACHA90, CH90a, Coq90, How88b, KC86b, BM81, Wey80]
[Gri88b, Gri88a, HHP87, Myh75] for other foundational theories
140
CHAPTER 7. ADVANCED TOPICS
Chapter 8
Summary and future views
For a powerful theorem proving system we need the following parts
• A maximum expressive language1
Otherwise there are ideas about proofs one can not express in full generality. If, for instance
we would restrict the language to first order constructs quantification over predicates and
functions would not be possible. As a result there would be several hinderances which
would cause a user of the system to lose enthusiasm dramatically2 .
– Instead of ` ∀P : T Y P E.F (P ) one would have to prove F (P0 ), F (P1 ), .. which
means reproving a simple proof several times simply because there is no way to
formulate what one really has in mind.
– Quantification over real numbers would not be possible.
This topic was presented in the course in many details
• A flexible user defined deductive apparatus
This includes tactics, tacticals, proved tactics, derived rules, etc.
• A highly cross-referenced modular library3
Such a library would allow to formulate a rather abstract theory and use its results in
other proofs.
We could, for instance, define a module for group theory as follows
MODULE: GROUP
G1:thm ` ...
G2:thm ` ...
.
G operations ◦ constants id
1
It has to be noted that there are authors who have a different opinion on this and believe in minimal
languages
2
which is an important factor for achieving results or not
3
Future Work
141
142
CHAPTER 8. SUMMARY AND FUTURE VIEWS
If then in another theory like calculus one has to deal with a fact that follows from group
theory one should be able to prove it “by GROUP”, i.e. by applying theorems from the
module GROUP.
• Modern user environments like good editors, file systems, etc.
The last point may be the main difference to the so-called “creative mathematics” since a
computer system simply can do a search in a library and will probably proceed in a way very
different from human beings. It may therefore be able to prove difficult theorems where no
proof exists so far.
Some people think that automated theorem proving is not worth any effort since at the time
present the systems are quite weak. But an instructive analogy to the world of chess playing
computers shows that there is a future for the theorem proving world.
From being a weak B-class in the early 70’s chess computers today are better than
most human players. This did not happen because of revolutionary new ideas but
mainly because of the improvement of hardware. Since now millions of steps can be
considered in a reasonable time it was possible to just take the best partial ideas
(like tree search and board evaluation) regardless of their complexity and put them
together.
In theorem proving also the major components (rule generator, tactic box, library, principles)
already exist and are not likely to change very much. We probably will not need any new
principal concept beyond these. However, efforts have to be put into the following areas.
• Details of any component need to be filled in. This includes type studies, particularly
recursive types, partial functions, and self-reflection.
• The library part of NuPRL needs to be improved. Currently this is the weakest component
of NuPRL.
• An improvement of the computing power is desirable. A factor of 100 is not out of reach
and would be enough to allow much more computation instead of user interaction.
The general idea presented during this course has been proven to be effective and is worth being
supported further. Everybody who works in it from now on can only expect to do partial work,
i.e. fill in details.
Chapter 9
Glossar, Index, ToC
ToC/Glossar liste aller design decisions
reduktion, sets, void, props as, dual-elim (hidden terms),....
+ consequences
Liste von Übersetzungen wichtiger begriffe
9.1
Natural deduction
tabellen der nat deduction für klassisch, intuitionistisch für Übungen.
9.2
Details of the type system
Exten: im Wesentlichen alle Tabellen aus NuPRL 8.1.
summary aller rules etc. auf dem heutigen stand + NuPRL short manual
NuPRL TYPES AND CONSTRUCTORS
atomic types:
canonical members
int
atom
void
...-1, 0, 1,...
”....”
none
type constructors
A#B
A|B
A− > B
Alist
x : A#B
x : A− > B
x : A|B
< a, b >
a in A, b in B
inl(a), inr(b)
. .
λx.b
. .
a.l
. , l in Alist
< a, b >
. , b in B[a/x]
λx.b
. .
members a of A satisfying condition B[a/x]
143
144
CHAPTER 9. GLOSSAR, INDEX, TOC
x, y : A//B
members of A
(Equality changed: a = a0 iff B[a, a0 /x, y] )
rec(z, x.T ; A)
A >B
members of T [λx.rec(z, x.T ; x), A/z, x]
(partial functions from A to B
propositions as types
a = a0 inA
i<j
axiom, if a = a0 , empty type otherwise
not wellformed if a(a0 ) not a member of A
axiom, if i < j, empty type otherwise
Typestructure is extremely rich but undecidable (because of dependent types).
Wellformedness cannot be checked automatically.
Typechecking has to become part of the theorem proving process (user
defined typechecking): show that a type belongs to some universe.
Universes
U1
U2
U3
.
.
atomic types and everything that can be
constructed via type constructors.
U 1, members of U 1, and everything that can be
constructed via type constructors.
U 2,........
Universes allow higher-order reasoning too.
145
9.3. THE RULES
Definition mechanism in NuPRL
Creation: create an object of type DEF and type in a definition of the form
text<formal parameter:description>text == text
E.g. object one t on:
{1..<n:nat>} == {i:int| 0<i & (i < <n>+1) }
Using a definition: Instantiate the definition by typing Control-I and then the object name, e.g.
Control-I one to n. At the cursor’s position the template (left hand side) of the definition will
appear and values for parameters have to be filled in.
E.g. the template {1..<nat>} appears. Typing in 20 instantiates it to {1..20} .
Essentially, a definition is a text macro.
Proofs in NuPRL:
Sequent calculus of the form:
x1 : T1 , .., xn : Tn ` S [ext s]
“Under the assumption that xi are variables of type Ti a member s of S can be constructed”.
Baue große syntaxvergleichstabelle(n):
Nuprl Type, member, destructor, Logical equivalent, programming, ML-syntax, automath, coquand,
smith etc. auch fuer die wahl anderer begriffe (see ch. 2.2.)
9.3
The rules
Proof by stepwise refinement using refinement rules:
H ` S [ext s] BY rule-name
1. H1 ` S1 [ext s1 ]
.
.
n. Hk ` Sk [ext sk ]
Examples:
H ` A#B [ext < a, b >] BY intro
1. H ` A [ext a]
2. H ` B [ext b]
H ` x : A#B [ext < a, b >] BY intro a at Ui
1. H ` a in A
2. H ` B[a/x] [ext b]
3. H, x : A ` B in U i
H, f : (x : A− > B), H 0 ` T [ext t[f (a)/y]] BY elim f on a [new y]
1. H, f : (x : A− > B), H 0 ` a in A
2. H, f : (x : A− > B), H 0 ,
y : B[a/x], y = f (a)inB[a/x] ` T [ext t]
146
CHAPTER 9. GLOSSAR, INDEX, TOC
9.3.1
Functions
9.3.2
Products
9.3.3
Union
9.3.4
Booleans
Remark:
Not implemented in NuPRL
Rule Schemes 9.3.1
IN2
1. H ` IN2 ∈ U1 by intro
2. H ` 02 ∈ IN2 by intro
H ` 12 ∈ IN2 by intro
3. H ` cond(b; s; t) ∈ T by intro over z.T
1. H ` b ∈ IN2
2. H ` s ∈ T [02 /z]
3. H ` t ∈ T [12 /z]
9.3.5
Sets
9.3.6
Quotients
9.3.7
Atoms
incl atom-equality ist entscheidbar
9.3.8
Unit
Remark:
Not implemented in NuPRL
9.3.9
Void
9.3.10
Equality
9.3.11
Natural numbers
Remark:
Not implemented in NuPRL
9.4. IMPLEMENTATION
9.3.12
Integers
9.3.13
List
9.3.14
Recursive types
147
Simple recursive
9.3.15
Partial functions
9.3.16
Miscellaneous
9.3.17
9.3.18
9.4
9.4.1
Implementation
Commands
Names of library objects given to both NuPRL commands and CTRL-I now refer to the object with
the same name if there is one, or else to the first library entry whose name extends the given name.
See the NuPRL-book, chapter 7 for details.
Additional key bindings can be defined in your init file by using the function define-key-binding.
This requires a bit of knowledge about how Nuprl deals with characters internally. See the file
implementation-notes for more details on this.
148
CHAPTER 9. GLOSSAR, INDEX, TOC
Figure 9.1: NuPRL-commands
statt < > nehmen em font, key-namen nicht control sequenz
dump <first-obj> - <last-obj> to <file> Write a representation of the selected objects to the
file. If no filename is given, the name of the last file to be loaded is used.
Existing extractions of theorems are also written to the library file.
load <location> from <file> read a library produced by dump. Library entries are added starting
at the given location. Objects with names identical to already existing ones are not loaded.
Theorems are loaded in unexpanded form for faster loading.
load fully <location> from <file> : When ”load fully” is used in place of ”load”, the proofs of
theorem are expanded as they are loaded in. This guarantees that the library that is loaded is
correct.
create <name> <kind> <location> create a new object with the given name, of the named kind
(thm, def, ml, eval), at the given location
check <objects> make named objects available for use in other objects. The status will be updated.
When you check a theorem, if the proof is good then the extractor is called. Checking large
theorems will take long.
delete <objects> Remove the named objects from the library
view <objects> Invoke the appropriate editor (text- or refinement editor) to the named object.
eval put command window in EVAL mode. (terminated by C-x)
ml put command window in ML mode. (terminated by C-x)
save <name> delete the entire library and save it in the Lisp state, attaching the given name
restore <name> will cause NuPRL to revert to (a copy of) the state it was in when the ”save ¡name¿”
was done (destroying whatever is currently around)
states causes a list of the currently known state-names to be printed
copystate <state1> <state2> does what one would expect
kill <state> will cause the named state to go away
up / down Scroll the library up, or down, respectively. These commands take an optional numeric
argument – they scroll the library the specified number of pages (default 1)
move <objects> <location> move named objects to the position immediately afetr the specified
location
jump <object> jump to the named object
top / bottom Scroll the library to the top, or bottom, respectively.
exit Leave NuPRL
149
9.4. IMPLEMENTATION
Figure 9.2: NuPRL-keybindings
‘‘C-n’’: simultaneously press Control and ‘‘n’’. N̂ (caps) achtung - nonstandard
C-n, M-, next line
C-b, M-a backward one character / proof node
C-f, M-l forward one character / proof node
C-p, M-i previous line
C-2, C-s select object
C-h, Backspace Backward delete character
C-w, C-d, C-k, Delete Kill selected object (current character, or region if both ends are selected)
C-u kill line in command window
C-c, C-y copy (= yank)
C-l Long (multiple movements)
C-q Diag (for moving up a proof tree)
C-i, M-x Insert definition
C-m Toggle bracket Mode
C-t Invoke Transformation tactic
C-o write snapshot to Output file
Tab Command mode
C-x Exit
C-M-<charcter> Insert Special symbols according to table
Figure 9.3: NuPRL-mouse-effects
left Mouse-select
in library window: grap name of object and insert into current window.
in text window: mark object (don’t move cursor)
in refinement window: select object (rule and main goal for editing, others for display only)
middle Mouse-jump:
in library window: scroll proportionally
in text window: move cursor to position
in refinement window: move cursor to position (If pointed to a subgoal, the cursor will move in
the proof tree making the subgola to become the current top-goal)
right Mouse-help (documentation string diplayed in commad window)
150
CHAPTER 9. GLOSSAR, INDEX, TOC
List of Figures
4.1
Operator precedences
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
73
4.2
Terms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
74
4.3
Redices and contracta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
74
4.4
The general evaluation procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
75
4.5
The type equality judgement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
76
4.6
Equality judgements for members of a type . . . . . . . . . . . . . . . . . . . . . . . .
76
4.7
A straightforward solution to find a maximal segment sum . . . . . . . . . . . . . . . .
95
4.8
Sketch of the final proof . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
97
5.1
A sample Proof Editor Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
5.2
Variants of the basic axioms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
5.3
The arith algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
5.4
The MERGE algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
5.5
The equality algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
5.6
Important predefined tacticals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
9.1
NuPRL-commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
9.2
NuPRL-keybindings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
9.3
NuPRL-mouse-effects
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
151
152
LIST OF FIGURES
List of Tables
3.1
Interpretations of Judgements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
153
65
154
LIST OF TABLES
Bibliography
[AC90] Peter Aczel and D. Carlisle. The logical theory of constructions: A formal framework and
its implementation. In First workshop on logical frameworks, Antibes, May 1990, 1990.
[ACHA90] Stuart F. Allen, Robert L. Constable, Douglas J. Howe, and William E. Aitken. The
semantics of reflected proof. In John C. Mitchell, editor, LICS-90 — Proceedings of the
Fifth Annual Symposium on Logic in Computer Science, 1990, Philadelphia, PA, June 1990,
pages 95–106. IEEE Computer Society Press, 1990.
[Ack54] W. Ackermann. Solvable cases of the decision problem. North–Holland, Amsterdam, 1954.
[AL84] Luigia Aiello and Giorgio Levi. The uses of metaknowledge in AI systems. In Tim
O’Shea, editor, ECAI-84 — Proceedings of the 6 th European Conference on Artificial Intelligence, Pisa, Italy, September 1984, pages 705–717. Elsevier Science Publishers B.V.
(North–Holland) Amsterdam, 1984.
[All87a] Stuart Allen. A non-type-theoretic definition of Martin-Löf’s types. In David Gries, editor,
LICS-87 — Proceedings of the Second Annual Symposium on Logic in Computer Science,
Ithaca, New York, USA, June 1987, pages 215–224. IEEE Computer Society Press, 1987.
[All87b] Stuart Allen. A non-type-theoretic semantics for type-theoretic language. PhD thesis, Cornell University. Department of Computer Science, Ithaca, NY 14853-7501, December 1987.
TR 87-866.
[And71] Peter B. Andrews. Resolution in type theory. Journal of Symbolic Logic, 36(3):414–432,
September 1971.
[And86] Peter B. Andrews. An Introduction to mathematical logic and Type Theory: To Truth
through Proof. Academic Press, London, Orlando, 1986.
[Bac85] Roland C. Backhouse. Algorithm development in Martin-Löf’s Type Theory. Technical
report, Computer Science Department, University of Essex, England, 1985.
[Bac89] Roland C. Backhouse. Constructive Type Theory - an introduction. In Manfred Broy,
editor, Constructive Methods in Computer Science, volume 55 of NATO ASI Series, Series
F: Computer & System Sciences, pages 9–62. Springer Verlag, Berlin, Heidelberg, New-York,
1989.
[Bar81] Henk P. Barendregt. The Lambda Calculus. Its syntax and semantics, volume 103 of Studies
in Logic and The Foundations of Mathematics. North–Holland, Amsterdam, 1981. (revised
version 1984).
[Bas89] David A. Basin. Building theories in NuPRL. In A. R. Meyer and M. A. Taitslin, editors,
Logic at Botik 89, number 363 in Lecture Notes in Computer Science, pages 12–25. Springer
Verlag, Berlin, Heidelberg, New-York, 1989.
155
156
BIBLIOGRAPHY
[BC85] Joseph L. Bates and Robert L. Constable. Proofs as programs. ACM Transactions on
Programming Languages and Systems, 7(1):113–136, January 1985.
[BCM88a] Roland C. Backhouse, P. Chisholm, and Grant Malcolm. Do it yourself type theory (part
I). EATCS Bulletin, 34:68–110, 1988. Also in Formal aspects of computing 1:19-84, 1989.
[BCM88b] Roland C. Backhouse, P. Chisholm, and Grant Malcolm. Do it yourself type theory (part
II). EATCS Bulletin, 35:205–245, 1988.
[Ber68] Paul Bernays. Axiomatic Set Theory. North–Holland, Amsterdam, 1968.
[BG90] Lee Blaine and Allen Goldberg. Verifiably correct data type refinement. Technical report,
Kestrel Institute, November 1990.
[Bib87] Wolfgang Bibel. Automated Theorem Proving. Vieweg Verlag, Braunschweig, second edition, 1987.
[Bis67] Errett Bishop. Foundations of Constructive Analysis. McGraw-Hill, New York, 1967. revised and extended version: [?].
[Ble77] W. Bledsoe. Non-resolution theorem proving. Artificial Intelligence, 9(1):1–35, 1977.
[BM79] Robert S. Boyer and J. Strother Moore. A computational Logic. Academic Press, London,
New York, 1979.
[BM81] Robert S. Boyer and J. Strother Moore. Metafunctions: Proving them correct and using
them efficiently as new proof procedures. In Robert S. Boyer and J. Strother Moore, editors,
The Correctness Problem in Computer Science, pages 103–184. Academic Press, London,
New York, 1981.
[Bru80] N. G. De Bruijn. A survey of the project AUTOMATH. In J.P. Seldin and J.R. Hindley,
editors, To H. B. Curry: Essays on Combinatory Logic, Lambda Calculus and Formalism,
pages 579–606. Academic Press, London, New York, 1980.
[Bun89] Alan Bundy. Automatic guidance of program synthesis proofs. In Proceedings of the Workshop on Automating Software Design, IJCAI-89, Kestrel Institute, Palo Alto, pages 57–59,
1989.
[CAB+ 86] Robert L. Constable, Stuart F. Allen, H. Mark Bromley, W. Rance Cleaveland, J. F.
Cremer, Robert W. Harper, Douglas J. Howe, Todd B. Knoblock, Nax Paul Mendler,
Prakash Panangaden, Jim T. Sasaki, and Scott F. Smith. Implementing Mathematics with
the NuPRL proof development system. Prentice Hall, Englewood Cliffs, NJ, 1986.
[Car84] Luca Cardelli. A semantics of multiple inheritance. In Semantics of Data Types, number
173 in Lecture Notes in Computer Science, pages 51–67. Springer Verlag, Berlin, Heidelberg,
New-York, 1984.
[CC90] F. Cardone and M. Coppo. Two extendsions of Curry’s type inference system. In Piergiorgio
Odifreddi, editor, Logic and Computer Science, pages 19–76. Academic Press, London, 1990.
[CFC58] Haskell B. Curry, R. Feys, and W. Craig. Combinatory Logic, volume 1. North–Holland,
Amsterdam, 1958.
[CH85] Thierry Coquand and Gerard Huet. Constructions: A higher order proof system for mechanizing mathematics. In EUROCAL’85, pages 151–184, Linz, Austria, April 1985.
BIBLIOGRAPHY
157
[CH88] Thierry Coquand and Gerard Huet. The calculus of constructions. Information and Computation, 76:95–120, 1988.
[CH90a] Robert L. Constable and Douglas J. Howe. Implementing metamathematics as an approach
to automatic theorem proving. In R. B. Banerjee, editor, Formal techniques in Artificial
Intelligence, a sourcebook, pages 45–75. Elsevier Science Publishers B.V. (North–Holland)
Amsterdam, 1990.
[CH90b] Robert L. Constable and Douglas J. Howe. Nuprl as a general logic. In Piergiorgio
Odifreddi, editor, Logic and Computer Science, pages 77–90. Academic Press, London,
1990.
[Chi87] Paul Chisholm. Derivation of a parsing algorithm in Martin-Löf’s Type Theory. Science of
Computer Programming, 8:1–42, 1987.
[CHS72] Haskell B. Curry, J. Roger Hindley, and Jonathan P. Seldin. Combinatory Logic, volume 2.
North–Holland, Amsterdam, 1972.
[Chu40] Alonzo Church. A formulation of the simple theory of types. Journal of Symbolic Logic,
5:56–68, 1940.
[CJE82] Robert L. Constable, Scott D. Johnson, and Carl D. Eichenlaub. Introduction to the
PL/CV2 Programming Logic, volume 135 of Lecture Notes in Computer Science. Springer
Verlag, Berlin, Heidelberg, New-York, 1982.
[CKB85] Robert L. Constable, Todd B. Knoblock, and Joseph L. Bates. Writing programs that
construct proofs. Journal of Automated Reasoning, 1:285–326, 1985.
[CM85] Robert L. Constable and Nax Paul Mendler. Recursive definitions in Type Theory. In
Rohit Parikh, editor, Proceedings of the Logics of Programs Conference, Brooklyn, NY,
USA, June 1985, volume 193 of Lecture Notes in Computer Science, pages 61–78. Springer
Verlag, Berlin, Heidelberg, New-York, 1985.
[Con83] Robert L. Constable. Programs as proofs. Information Processing Letters, 16(3):105–112,
1983.
[Con84] Robert L. Constable. Mathematics as programming. In Edmund Clarke and Dexter Kozen,
editors, Logics of Programs, number 164 in Lecture Notes in Computer Science, pages 116–
128. Springer Verlag, Berlin, Heidelberg, New-York, 1984.
[Con85] Robert L. Constable. Constructive mathematics as a programming logic I: Some principles
of theory. Annals of Discrete Mathematics, 24:21–38, 1985.
[Con88] Robert L. Constable. Themes in the development of programming logics circa 1963-1987.
Annual Reviews in Computer Science, pages 147–165, 1988.
[Con89] Robert L. Constable. Assigning meaning to proofs: a semantic basis for problem solving
environments. In Manfred Broy, editor, Constructive Methods in Computer Science, volume 55 of NATO ASI Series, Series F: Computer & System Sciences, pages 63–94. Springer
Verlag, Berlin, Heidelberg, New-York, 1989.
[Coq90] Thierry Coquand. Metamathematical investigations of a calculus of constructions. In Piergiorgio Odifreddi, editor, Logic and Computer Science, pages 91–122. Academic Press, London, 1990.
158
BIBLIOGRAPHY
[CR36] Alonzo Church and B. J. Rosser. Some properties of conversion. Trans. Am. Math. Soc.,
39:472–482, 1936.
[CS87] Robert L. Constable and Scott Fraser Smith. Partial objects in constructive Type Theory.
In David Gries, editor, LICS-87 — Proceedings of the Second Annual Symposium on Logic
in Computer Science, Ithaca, New York, USA, June 1987, pages 183–193. IEEE Computer
Society Press, 1987.
[CS88] Robert L. Constable and Scott Fraser Smith. Computational foundations of basic recursive
function theory. In Yuri Gurevich, editor, LICS-88 — Proceedings of the Third Annual
Symposium on Logic in Computer Science, Edinburgh, Scotland, July 1988, pages 360–371.
IEEE Computer Society Press, 1988.
[Cur70] Haskell B. Curry. Outline of a formalist philosophy of mathematics. North–Holland, Amsterdam, 1970.
[Dij76] Edsger W. Dijkstra. A discipline of Programming. Prentice Hall, Englewood Cliffs, NJ,
1976.
[DM82] Luis Damas and Robin Milner. Principal type schemes for functional programs. In Proceedings of the 9th ACM Symposium on Principles of Programming Languages, pages 207–212,
1982.
[Dum77] Michael Dummett. Elements of Intuitionism. Oxford Logic Series. Clarenden Press, Oxford,
1977.
[FM88] Amy Felty and Dale Miller. Specifying theorem provers in a higher-order logic programming
language. In E. Lusk and R. Overbeek, editors, Proceedings of the 9 th Conference on Automated Deduction, Argonne, Illinois, May 1988, volume 310 of Lecture Notes in Computer
Science, pages 61–80. Springer Verlag, Berlin, Heidelberg, New-York, 1988.
[Gal86] Jean H. Gallier. Logic for Computer Science: Foundations of Automated Theorem Proving.
Harper and Row, New York, 1986.
[Gen35] Gerhard Gentzen. Untersuchungen über das logische Schließen. Mathematische Zeitschrift,
39:176–210, 405–431, 1935. English Translation: “Investigations into logical deduction” in
[?] pages 68-131.
[Gir71] Jean-Yves Girard. Une extension de l’interpretation de godel a l’analyse, et son application
a l’elimination des coupures dans l’analyse at la theorie des types. In J. Fenstad, editor,
Proceedings of the second Scandinavian Logic Symposium, pages 63–92. North–Holland,
Amsterdam, 1971.
[Gir72] Jean-Yves Girard.
Interpretation fonctionelle et elimination des coupures dans
l’arithmetique d’ordre superieur. PhD thesis, Universsite Paris VII, 1972.
[Gir86] Jean-Yves Girard. The system F of variable types: Fifteen years later. Theoretical Computer Science, 45:159–192, 1986.
[GLT89] Jean-Yves Girard, Yves Lafont, and Paul Taylor. Proofs and Types. Cambridge University
Press, 1989.
[GMW79] Michael J. Gordon, Robin Milner, and Christopher P. Wadsworth. Edinburgh LCF: A
mechanized Logic of Computation. Number 78 in Lecture Notes in Computer Science.
Springer Verlag, Berlin, Heidelberg, New-York, 1979.
BIBLIOGRAPHY
159
[Gri81] David Gries. The science of programming. Springer Verlag, Berlin, Heidelberg, New-York,
1981.
[Gri88a] Timothy George Griffin. Notational definition - a formal account. In Yuri Gurevich, editor,
LICS-88 — Proceedings of the Third Annual Symposium on Logic in Computer Science,
Edinburgh, Scotland, July 1988, pages 372–383. IEEE Computer Society Press, 1988.
[Gri88b] Timothy George Griffin. Notational definition and top-down refinement for interactive proof
development systems. PhD thesis, Cornell University. Department of Computer Science,
Ithaca, NY 14853-7501, August 1988. TR 88-937.
[GS89] Fausto Giunchiglia and Alan Smaill. Reflection in constructive and non-constructive automated reasoning. In Harvey Abramson and M. H. Rogers, editors, Meta-Programming in
Logic Programming, chapter 6, pages 123–140. MIT Press, Cambridge Mass., 1989.
[Hay86] S. Hayashi. PX: a system extracting programs from proofs. In Proceedings of the IFIP
Confereence on Formal Description of Programming Concepts, pages 399–424, 1986.
[Hey31] Arend Heyting. Die intuitionistische Grundlegung der Mathematik. Erkenntnis, 2:106–115,
1931.
[Hey71] Arend Heyting. Intuitionism: An Introduction. North–Holland, Amsterdam, 3 rd edition,
1971.
[HHP87] Robert Harper, Furio Honsell, and Gordon Plotkin. A framework for defining logics. In
David Gries, editor, LICS-87 — Proceedings of the Second Annual Symposium on Logic in
Computer Science, Ithaca, New York, USA, June 1987, pages 194–204. IEEE Computer
Society Press, 1987.
[Hin69] J. Roger Hindley. The principal type scheme of an object in combinatory logic. Transactions
of the American Mathematical Society, 146:29–60, 1969.
[Hin83] J. Roger Hindley. The completeness theorem for typing λ-terms. Theoretical Computer
Science, 22:1–17, 1983.
[Hoa72] Charles Antony Richard Hoare. Notes on data structuring. In [?], pages 83–174. Academic
Press, London, 1972.
[Hoa75] C. A. R. Hoare. Recursive data structures. International Journal of Computer and Information Sciences, 4(2):105–132, June 1975.
[How80] W. Howard. The formulas-as-types notion of construction. In J. Roger Hindley and
Jonathan P. Seldin, editors, To H. B. Curry: Essays on Combinatory Logic, Lambda Calculus and Formalism, pages 479–490. Academic Press, London, New York, 1980. First
published 1969.
[How86] Douglas J. Howe. Implementing number theory: An experiment with NuPRL. In J. H. Siekmann, editor, Proceedings of the 8th Conference on Automated Deduction, Oxford, England,
1986, volume 230 of Lecture Notes in Computer Science, pages 404–415. Springer Verlag,
Berlin, Heidelberg, New-York, 1986.
[How87] Douglas J. Howe. The computational behaviour of girard’s paradox. In David Gries, editor,
LICS-87 — Proceedings of the Second Annual Symposium on Logic in Computer Science,
Ithaca, New York, USA, June 1987, pages 205–214. IEEE Computer Society Press, 1987.
160
BIBLIOGRAPHY
[How88a] Douglas J. Howe. Automating reasoning in an implementation of constructive Type Theory.
PhD thesis, Cornell University. Department of Computer Science, Ithaca, NY 14853-7501,
June 1988. TR 88-925.
[How88b] Douglas J. Howe. Computational metatheory in NuPRL. In Proceedings of the 9 th Conference on Automated Deduction, Argonne, Illinois, May 1988, pages 238–257, 1988.
[How89] Douglas J. Howe. Equality in lazy computation systems. In Rohit Parikh, editor, LICS-89
— Proceedings of the Fourth Annual Symposium on Logic in Computer Science, 1989, pages
198–203. IEEE Computer Society Press, 1989.
[HR67] jr. Hartley Rogers. Theory of recursive functions and effective computability. MIT Press,
Cambridge, MA, 1967.
[HRS90] M. Heisel, W. Reif, and W. Stephan. Tactical theorem proving in program verification. In
M. E. Stickel, editor, Proceedings of the 10 t h Conference on Automated Deduction, Kaiserslautern, Germany, July 1990, number 449 in Lecture Notes in Computer Science, pages
117–131. Springer Verlag, Berlin, Heidelberg, New-York, 1990.
[HS86] J. Roger Hindley and Jonathan P. Seldin. Introduction to combinators and λ-calculus.
Cambridge University Press, 1986.
[Hue86] Gérard Huet. Deduction and computation. In Wolfgang Bibel and Ph. Jorrand, editors,
Fundamentals of Artificial Intelligence — An Advanced Course, volume 232 of Lecture Notes
in Computer Science, pages 39–74. Springer Verlag, Berlin, Heidelberg, New-York, 1986.
[KC86a] Todd B. Knoblock and Robert L. Constable. Formalized metareasoning in Type Theory.
Technical Report TR 86-742, Cornell University. Department of Computer Science, Ithaca,
NY 14853-7501, March 1986.
[KC86b] Todd B. Knoblock and Robert L. Constable. Formalized metareasoning in Type Theory.
In LICS-86 — Proceedings of the First Annual Symposium on Logic in Computer Science,
1986. IEEE Computer Society Press, 1986.
[Kle52] Stephen C. Kleene. Introduction to Metamathematics. Van Nostrand, Princeton, NJ, 1952.
[Kno87] Todd B. Knoblock. Metamathematical extensibility in Type Theory. PhD thesis, Cornell
University. Department of Computer Science, Ithaca, NY 14853-7501, December 1987. TR
87-892.
[Kol32] A. N. Kolmogorov. Zur Deutung der intuitionistischen Logik. Mathematische Zeitschrift,
35:58–65, 1932.
[Kre86] Christoph Kreitz. Constructive automata theory implemented with the NuPRL proof development system. Technical Report TR 86-779, Cornell University. Department of Computer
Science, Ithaca, NY 14853-7501, August 1986.
[Lak76] Imre Lakatos. Proofs and Refutations. Cambridge University Press, Cambridge, 1976.
[Lei90] Daniel Leivant. Contracting proofs to programs. In Piergiorgio Odifreddi, editor, Logic and
Computer Science, pages 279–328. Academic Press, London, 1990.
[LSBB90] Reinhold Letz, Johannes Schumann, Stephan Bayerl, and Wolfgang Bibel. Setheo — a
high-performance theorem prover for first-order logic. Journal of Automated Reasoning,
1990.
BIBLIOGRAPHY
161
[Men87a] Paul Francis Mendler. Inductive definition in Type Theory. PhD thesis, Cornell University.
Department of Computer Science, Ithaca, NY 14853-7501, September 1987. TR 87-870.
[Men87b] Paul Francis Mendler. Recursive types and type constraints in second order lambda calculus.
In David Gries, editor, LICS-87 — Proceedings of the Second Annual Symposium on Logic
in Computer Science, Ithaca, New York, USA, June 1987, pages 30–36. IEEE Computer
Society Press, 1987.
[Mil78] Robin Milner. A theory of type polymorphism in programming. Journal of Computer and
System Sciences, 17(3):348–375, December 1978.
[Min63] M. Minsky. Steps toward artificial intelligence. Computers and Thought, pages 406–450,
1963.
[ML70] Per Martin-Löf. A theory of types. unpublished manuscript, 1970.
[ML73] Per Martin-Löf. An intuitionistic theory of types: predicative part. In H. E. Rose and J. C.
Shepherdson, editors, Logic Colloquium ’73, Amsterdam, 1973. North–Holland, Amsterdam.
[ML82] Per Martin-Löf. Constructive mathematics and computer programming. In 6-th International Congress for Logic, Methodology and Philosophy of Science, 1979, pages 153–175.
North–Holland, Amsterdam, 1982.
[ML84] Per Martin-Löf. Intuitionistic Type Theory, volume 1 of Studies in Proof Theory Lecture
Notes. Bibliopolis, Napoli, 1984.
[MPC86] Paul Francis Mendler, Prakash Panangaden, and Robert L. Constable. Infinite objects in
Type Theory. Technical Report TR 86-743, Cornell University. Department of Computer
Science, Ithaca, NY 14853-7501, March 1986.
[MW85] Zohar Manna and Richard J. Waldinger. The logical basis for computer programming,
volume I: Deductive Reasoning. Addison Wesley, Reading, MA, 1985.
[Myh75] John Myhill. Constructive set theory. Journal of Symbolic Logic, 40(3):347–383, September
1975.
[NO79] Greg Nelson and Derek. C. Oppen. Simplification by cooperating decision procedures. ACM
Transactions on Programming Languages and Systems, 1(2):245–257, October 1979.
[NO80] Greg Nelson and Derek. C. Oppen. Fast decision procedures based on congruence closure.
Journal of the Association for Computing Machinery, 27(2):356–364, April 1980.
[NPS90] Bengt Nordström, Kent Petersson, and Jan M. Smith. Programming in Martin-Löfs Type
Theory. An introduction. Clarendon Press, Oxford, 1990.
[NS84] Bengt Nordström and Jan M. Smith. Propositions and specifications of programs in MartinLöfs Type Theory. BIT, 24:288–301, 1984.
[NSS63] A. Newell, M. Shaw, and H. Simon. Empirical explorations with the logic theory machine.
Computers and Thought, pages 109–133, 1963.
[Pau87] Lawrence C. Paulson. Logic and Computation: Interactive Proof with Cambridge LCF.
Cambridge University Press, 1987.
[Pol45] G. Polya. How to solve it. Princeton University Press, Princeton, New Jersey, 1945.
[Pra65] Dag Prawitz. Natural Deduction: A Proof-Theoretical study. Almquist & Wiksell, 1965.
162
BIBLIOGRAPHY
[Qui63] Willard Van Orman Quine. Set Theory and its logic. Belknap Press, Cambridge, MA, 1963.
[Rey81] John C. Reynolds. The craft of programming. Prentice Hall, Englewood Cliffs, NJ, Englewood Cliffs, N.J., 1981.
[Ric78] Michel M. Richter.
Logikkalküle, volume 43 of Teubner Studienbücher Informatik.
B.G.Teubner, Stuttgart, 1978.
[Rob65] J. A. Robinson. A machine-oriented logic based on the resolution principle. Journal of the
Association for Computing Machinery, 12(1):23–41, January 1965.
[Rus08] Bertrand Russel. Mathematical logic as based on a theory of types. Am. J. of Math.,
30:222–262, 1908.
[Sas85] James T. Sasaki. The Extraction and Optimization of Programs from Constructive Proofs.
PhD thesis, Cornell University. Department of Computer Science, Ithaca, NY 14853-7501,
1985.
[Sch77] Kurt Schütte. Proof Theory. Springer Verlag, Berlin, Heidelberg, New-York, 1977.
[Sch85] Alan H. Schoenfield. Mathematical Problem Solving. Academic Press, London, 1985.
[Smi83] Jan M. Smith. The identification of propositions and types in Martin-Löf’s Type Theory: A
programming example. In International Conference on Foundations of Computation Theory, Borgholm, Sweden, August 1983, pages 445–456. Springer Verlag, Berlin, Heidelberg,
New-York, 1983.
[Smi84] Jan M. Smith. An interpretation of Martin-Löf’s Type Theory in a type-free theory of
propositions. Journal of Symbolic Logic, 49(3):730–753, 1984.
[Smi88] Scott Fraser Smith. Partial objects in Type Theory. PhD thesis, Cornell University. Department of Computer Science, Ithaca, NY 14853-7501, August 1988. TR 88-938.
[Ste72] Sören Stenlund. Combinators, λ-terms and Proof Theory. D. Reidel, Dordrecht, The
Netherlands, 1972.
[Sup72] Patrick Suppes. Axiomatic Set Theory. Dover Publications, 1972.
[Tai67] William W. Tait. Intensional interpretation of functionals of finite type. Journal of Symbolic
Logic, 32(2):187–199, 1967.
[Tak75] Gaisi Takeuti. Proof Theory. North–Holland, Amsterdam, 1975.
[Tur84] R. Turner. Logics for Artificial Intelligence. Ellis Horwood Ltd., 1984.
[vBJ77] L. S. van Benthem Jutting. Checking Landau’s Grundlagen in the AUTOMATH System.
PhD thesis, Eindhoven University of Technology, Eindhoven, Netherlands, March 1977.
also: Mathematical Centre Tracts 83, Math. Centre, Amsterdam, 1979.
[vH67] J. van Heijenoort. From Frege to Gödel: A Sourcebook of Mathematical Logic. Harvard
University Press, Cambridge, Massachusetts, 1967.
[Wey80] Richard W. Weyhrauch. Prolegomena to theory of mechanized formal reasoning. Artificial
Intelligence, 13:133–170, 1980.
[WOLB84] Larry Wos, Russ Overbeek, Ewing Lusk, and J. Boyle. Automated Reasoning. Prentice
Hall, Englewood Cliffs, NJ, 1984.
BIBLIOGRAPHY
163
[WR25] Alan N. Whitehead and Bertrand Russell. Principia Mathematicae, volume 1. Cambridge
University Press, Cambridge, MA, 1925.
© Copyright 2026 Paperzz