# Coq3110An Introduction to Coq for CS 3110

This material is based on an online textbook by Benjamin Pierce et al. titled "Software Foundations":
```    http://www.cis.upenn.edu/~bcpierce/sf/
```

# Inductive Types

Coq is a functional programming language. We can define data types, just like in OCaml. For example:
• Days of the week
• Boolean
• Natural numbers

## Days of the Week

A datatype definition:

Inductive day : Type :=
| monday : day
| tuesday : day
| wednesday : day
| thursday : day
| friday : day
| saturday : day
| sunday : day.

A function on days:

Definition next_weekday (d:day) : day :=
match d with
| mondaytuesday
| tuesdaywednesday
| wednesdaythursday
| thursdayfriday
| fridaymonday
| saturdaymonday
| sundaymonday
end.

Check checks the type of an expression.

Check next_weekday.
(* ===> next_weekday : day -> day *)

### Computation

Eval compute in e evaluates e and prints the result, much like entering e into the REPL in OCaml.

Eval compute in (next_weekday friday).
(* ==> monday : day *)
Eval compute in (next_weekday (next_weekday saturday)).
(* ==> tuesday : day *)

### Unit tests

A "unit test" for our function — i.e., a mathematical claim about its behavior:

Example test_next_weekday:
(next_weekday (next_weekday saturday)) = tuesday.

A proof script giving evidence for the claim:

Proof. reflexivity. Qed.

reflexivity is a tactic that is built into Coq. In essence, it applies Coq's computational rules (i.e., dynamic semantics) to both side of the = sign. Then it compares to see whether both sides reduced to the same value. If so, that counts as evidence that the equality holds.

### Extraction into OCaml

Extraction day.
(* type day =
| Monday
... *)

Extraction next_weekday.
(* let next_weekday = function
| Monday -> Tuesday
... *)

## Booleans

A familiar datatype:

Inductive bool : Type :=
| true : bool
| false : bool.

Booleans are also provided in Coq's standard library, but we are defining from scratch, just to see how it's done.

### Functions on booleans

We can code these up with using any built-in boolean operators.

Definition negb (b:bool) : bool :=
match b with
| truefalse
| falsetrue
end.

Coq has an if expression that we could use instead of pattern matching.

Definition andb (b1:bool) (b2:bool) : bool :=
if b1 then b2 else false.

Definition orb (b1:bool) (b2:bool) : bool :=
if b1 then true else b2.

### Unit tests

These test acheive complete coverage of orb:

Example test_orb1: (orb true false) = true.
Proof. reflexivity. Qed.
Example test_orb2: (orb false false) = false.
Proof. reflexivity. Qed.
Example test_orb3: (orb false true) = true.
Proof. reflexivity. Qed.
Example test_orb4: (orb true true) = true.
Proof. reflexivity. Qed.

## Natural Numbers

The natural numbers in unary representation:

Inductive nat : Type :=
| O : nat
| S : natnat.

The clauses of this definition can be read:
• O is a natural number (note that this is the letter "O," not the numeral "0").
• S is a "constructor" that takes a natural number and yields another one — that is, if n is a natural number, then S n is too.

### Two functions on numbers

Definition succ (n : nat) : nat :=
S n.

Subtract one:

(* requires: n >= 1 *)
Definition pred (n : nat) : nat :=
match n with
| OO
| S n'n'
end.

### Syntactic sugar for numbers

Arabic numerals can be used in input as a shorthand for sequences of applications of S to O, and Coq uses the same shorthand on output:

Check (S (S (S (S O)))).
(* ===> 4 *)
Eval compute in (pred 4).
(* ===> 3 *)

### Recursive functions

Recursive functions are defined using Fixpoint instead of Definition:

Fixpoint evenb (n:nat) : bool :=
match n with
| Otrue
| S Ofalse
| S (S n') ⇒ evenb n'
end.

We can define oddb in terms of evenb:

Definition oddb (n:nat) : bool :=
negb (evenb n).

Example test_oddb1: (oddb 1) = true.
Proof. reflexivity. Qed.
Example test_oddb2: (oddb 4) = false.
Proof. reflexivity. Qed.

### Arithmetic

Fixpoint plus (n : nat) (m : nat) : nat :=
match n with
| Om
| S n'S (plus n' m)
end.

When two arguments have the same type, we can list them together. (n m : nat) means the same as (n : nat) (m : nat).

Fixpoint mult (n m : nat) : nat :=
match n with
| OO
| S n'plus m (mult n' m)
end.

Fixpoint minus (n m:nat) : nat :=
match n, m with
| O , _O
| S _ , On
| S n', S m'minus n' m'
end.

### Factorial

Fixpoint factorial (n:nat) : nat :=
match n with
| O ⇒ 1
| S n'mult n (factorial n')
end.

Example test_factorial1: (factorial 3) = 6.
Proof. reflexivity. Qed.
Example test_factorial2: (factorial 5) = (mult 10 12).
Proof. reflexivity. Qed.

### Extensible Syntax

Notation "x + y" := (plus x y)
(at level 50, left associativity) : nat_scope.
Notation "x - y" := (minus x y)
(at level 50, left associativity) : nat_scope.
Notation "x × y" := (mult x y)
(at level 40, left associativity) : nat_scope.

Check ((0 + 1) + 1).

Theorem plus_O_n : ∀ n : nat, 0 + n = n.
Proof. reflexivity. Qed.

# Logic

Coq is also a proof assistant. Coq's built-in logic has:
• Inductive definitions
• (universal quantification)
• (implication)
• that's it!
Everything else ('and', 'or', 'negation', 'equals', ...) can be coded up, and is in the standard library.

## Propositions

In Coq, the type of things that can (potentially) be proven is Prop.
Here is an example of a provable proposition:

Check (3 = 3).
(* ===> Prop *)

Here is an example of an unprovable proposition:

Check (∀ (n:nat), n = 2).
(* ===> Prop *)

### Values of type Prop

Types are inhabited by values.
• true and false inhabit bool.
• 0, 1, ... inhabit nat.
• what inhabits Prop?
The propositions we try to prove!
• e.g., 0×3 = 0 inhabits Prop.
But propositions are just another kind of type...
• what inhabits the type 0×3 = 0?
A proof that provides evidence that 0×3 = 0!

## Proofs

Propositions are inhabited by proof objects aka proof terms.

Lemma silly : 0 × 3 = 0.
Proof. reflexivity. Qed.
Print silly.
(* ===> silly = eq_refl : 0 * 3 = 0 *)

(Here, the eq_refl proof object provides evidence for the equality. We'll come back to how it does that...)

### Constructing proof objects

We could even have written the proof object ourselves:

Definition silly' : 0 × 3 = 0 :=
eq_refl.
Print silly'.
Print silly.
(* ===> silly' = eq_refl : 0 * 3 = 0 *)
(* ===> silly = eq_refl : 0 * 3 = 0 *)

These mean the same thing:
• Lemma name : prop. Proof. tactics Qed.
• Definition name : prop := proof object .
The first form lets us interactively build a proof object, the latter requires us to state it all at once.

### Another Proof Object

Print plus_O_n.
(* ===> plus_O_n =
fun n : nat
=> eq_refl
: forall n : nat, 0 + n = n *)

This proof object is a function that takes in n and returns a proof object eq_refl.

We read name = expr : type the same, whether the type is Prop or Type.

Print andb.
(* ===> andb =
fun b1 b2 : bool
=> if b1 then b2 else false
: bool -> bool -> bool *)

Print plus_O_n.
(* ===> plus_O_n =
fun n : nat
=> eq_refl
: forall n : nat, 0 + n = n *)

Coq unifies the notions of
• types with formulas, and
• programs with proofs.

## Coq's Connectives

Same connectives we saw in IQC:
• Implication
• Universal quantification
• Conjunction
• Disjunction
• True and False
• Negation ¬
• Existential quantification
• Equality =

## Implies and forall

These are the built-in connectives in Coq.
Coq treats both connectives the same way:
• The proof object for P Q is a function that takes evidence for P as input and produces evidence for Q as output.
• The proof object for x, P is a function that takes x as input and produces evidence for P as output.

### Implies and forall intro

The introduction rules in IQC corresponds to the intros tactic in Coq.
The intros tactic moves one or more quantifiers or hypotheses from the goal to a "context" of current assumptions.

Lemma imp_intro : (1 + 1) = 2 → 0 × 3 = 0.
Proof. intros H. reflexivity. Qed.
Print imp_intro.
(* ===> imp_intro =
fun _ : 1 + 1 = 2 => eq_refl
: 1 + 1 = 2 -> 0 * 3 = 0 *)

The proof object takes in evidence for 1+1=2, discards that evidence, and returns evidence for 0×3=0.

Lemma forall_intro : ∀ (n:nat), n = n.
Proof. intros n. reflexivity. Qed.
Print forall_intro.
(* ===> forall_intro =
fun n : nat => eq_refl
: forall n : nat, n = n *)

The proof object takes in n, and returns evidence for n=n.

### Implies and forall elim

The elimination rules for these connectives in IQC correspond to the apply tactic in Coq.

Lemma imp_elim : ∀ (P Q : Prop), P → (PQ) → Q.
Proof.
intros P Q. intros HP HPimpQ.
apply HPimpQ. assumption.
Qed.
Print imp_elim.
(* ===> imp_elim = fun (P Q : Prop) (HP : P)
(HPimpQ : P -> Q)
=> HPimpQ HP
: forall P Q : Prop,
P -> (P -> Q) -> Q *)

Note:
• The assumption tactic corresponds to the IQC assumption rule.
• The proof object applies a function. Implication elimination is really function application!

Lemma forall_elim : (∀ (n:nat), n=0) → 1=0.
Proof. intros H. apply H with (n:=1). Qed.
Print forall_elim.
(* ===> forall_elim =
fun H : forall n : nat, n = 0 => H 1
: (forall n : nat, n = 0) -> 1 = 0 *)

## Conjunction

Logical conjunction is not built-in to the language, though it's available in the standard library.
Conjunction is a binary operator on propositions:

Inductive and (P Q : Prop) : Prop :=
conj : PQ → (and P Q).

Notation "P ∧ Q" := (and P Q) : type_scope.

### And intro

And intro in IQC corresponds to applying the conj constructor in Coq.

Theorem and_intro :
(0 = 0) ∧ (4 = mult 2 2).
Proof.
apply conj. reflexivity. reflexivity. Qed.

Print and_intro.
(* ===>  and_intro =
conj (0 = 0) (4 = 2 * 2)
eq_refl eq_refl
: 0 = 0 /\ 4 = 2 * 2 *)

### And elim

And elim in IQC corresponds to the inversion tactic in Coq, which breaks apart the evidence for a Prop into smaller pieces of evidence.

Theorem and_elim : ∀ P Q : Prop,
PQP.
Proof.
intros P Q H.
inversion H as [HP HQ].
apply HP.
Qed.

### A proof we did in IQC

Theorem and_commut : ∀ P Q : Prop,
PQQP.
Proof.
intros P Q H.
inversion H as [HP HQ].
apply conj.
apply HQ.
apply HP.
Qed.

Writing tactics is the "assembly language" programming of Coq. There are automated tactics that find proofs for us!

Theorem and_commut' : ∀ P Q : Prop,
PQQP.
Proof. firstorder. Qed.

# Disjunction

Inductive or (P Q : Prop) : Prop :=
| or_introl : Por P Q
| or_intror : Qor P Q.

Notation "P ∨ Q" := (or P Q) : type_scope.

Check or_introl.
(* ===>  forall P Q : Prop, P -> P \/ Q *)

Check or_intror.
(* ===>  forall P Q : Prop, Q -> P \/ Q *)

## A proof we did in IQC

Theorem or_commut : ∀ P Q : Prop,
PQQP.
Proof.
intros P Q H.
inversion H as [HP | HQ].
apply or_intror. apply HP.
apply or_introl. apply HQ.
Qed.

We could even write down an explicit proof object for or_commut without using tactics to construct it:

Definition or_commut' : ∀ P Q,
PQQP
:=
fun (P Q : Prop) (H : PQ) ⇒
match H with
| or_introl HPor_intror Q P HP
| or_intror HQor_introl Q P HQ
end.

Or we could let Coq find the proof.

Theorem or_commut'' : ∀ P Q : Prop,
PQQP.
Proof. firstorder. Qed.

## True and False

True has a single constructor that takes no arguments.

Inductive True : Prop :=
I : True.

False has no constructors. Intuition: False is a proposition for which there is no way to give evidence.

Inductive False : Prop := .

## Proofs with True and False

Applying the I constructor corresponds to IQC's true intro.

Theorem True_is_provable : True.
Proof. apply I. Qed.

Once we have False as an assumption, the contradiction tactic lets us conclude whatever we want. That corresponds to IQC's false elim.

Theorem False_implies_nonsense :
False → 2 + 2 = 5.
Proof.
Qed.

Theorem exfalso : ∀ (P:Prop),
FalseP.
Proof.
Qed.

## Negation

Negation is defined in Coq exactly as in IQC. The fold and unfold tactics let us convert between ¬P and PFalse.

Definition not (P:Prop) := PFalse.
Notation "¬ x" := (not x) : type_scope.

Theorem not_False : ¬ False.
Proof. unfold not. apply exfalso. Qed.

∀ P Q : Prop, (P ∧ ¬P) → Q.
Proof. firstorder. Qed.

## Existential Quantification

Inductive ex (X:Type) (P : XProp) : Prop :=
ex_intro : ∀ (witness:X), P witnessex X P.

To give evidence we must actually name a witness a specific value x — and then give evidence for P x.

Notation "'exists' x , p" := (ex _ (fun xp))
(at level 200, x ident, right associativity) : type_scope.
Notation "'exists' x : X , p" := (ex _ (fun x:Xp))
(at level 200, x ident, right associativity) : type_scope.

### Proof with exists

The ex_intro constructor corresponds to IQC's exists intro.

Example exists_example_1 :
∃ n, n + (n × n) = 6.
Proof.
apply ex_intro with (witness:=2).
reflexivity.
Qed.

Note that we explicitly give the witness.
We'll omit exists elimination, though it also is in Coq.

### A proof we did in IQC

Theorem dist_exists_or : ∀ (X:Type) (P Q : XProp),
(∃ x, P xQ x) ↔ (∃ x, P x) ∨ (∃ x, Q x).
Proof.
firstorder.
Qed.

## Equality

The equality relation is definable, not built-in to the language.

Inductive eq {X:Type} : XXProp :=
refl_equal : ∀ x, eq x x.

Notation "x = y" := (eq x y)
(at level 70, no associativity) : type_scope.

Lemma four: 2 + 2 = 1 + 3.
Proof.
apply refl_equal.
Qed.

reflexivity is essentially just apply refl_equal.

## Excluded middle

Note that some theorems that are true in classical logic are not provable in Coq's (constructive) logic. E.g., let's look at how this proof gets stuck...

Theorem excluded_middle : ∀ P : Prop,
P ∨ ¬P.
Proof.
intros P. unfold not.
(* We either have to go left or right... *)
left. (* But now what?  We don't have evidence for P. *)
Undo.
right. intros HP. (* And now we don't have evidence for False. *)
Abort.

# Proofs from IPC and IQC

Here are Coq proofs for all the theorems we proved in IQC and IPC. The firstorder tactic searches for, and finds, a proof object for each of these theorems. You can enter Print <theorem_name> to see that object.

Theorem lec19thm1 : ∀ (A B : Prop),
A → (BA).
Proof. firstorder. Qed.

Theorem lec19thm2 : ∀ (A B : Prop),
A → (B → (AB)).
Proof. firstorder. Qed.

Theorem lec19thm3 : ∀ (A B : Prop),
(AB) → (BA).
Proof. firstorder. Qed.

Theorem rec18thm1 : ∀ (A B : Prop),
(AB) → A.
Proof. firstorder. Qed.

Theorem rec18thm2 : ∀ (A B : Prop),
(AB) → (BA).
Proof. firstorder. Qed.

Theorem rec18thm3 : ∀ (A B C : Prop),
(AB) → ((BC) → (AC)).
Proof. firstorder. Qed.

Theorem rec18thm4 : ∀ (S C O : Prop),
((SC) ∧ O ∧ ((O->~C) ∧ (C->~O))) → ¬S.
Proof. firstorder. Qed.

Theorem lec21thm1 : ∀ (Q R : TypeProp),
(∀ x, R(x) ∧ Q(x)) → (∀ x, R(x)) ∧ (∀ x, Q(x)).
Proof. firstorder. Qed.

Theorem lec21thm2 : ∀ (Q R : TypeProp),
(∃ x, Q(x) ∨ R(x)) → (∃ x, R(x)) ∨ (∃ x, Q(x)).
Proof. firstorder. Qed.

Theorem rec19thm1 : ∀ (A B : Prop),
((AB) ∧ ¬B) → ¬A.
Proof. firstorder. Qed.

Theorem rec19thm2 : ∀ (A B : Prop),
(A → (B ∨ (AB))) → (AB).
Proof. firstorder. Qed.

Theorem rec19thm3 : ∀ (A B : Prop),
~((~A ∨ ¬B) ∧ (AB)).
Proof. firstorder. Qed.

Theorem rec19thm4 : ∀ (P Q : TypeProp),
(∀ (x y : Type), (P(x) → Q(y))) ∧ (∃ x, P(x))
→ (∃ y, Q(y)).
Proof. firstorder. Qed.

Theorem rec19thm5 : ∀ (P Q : TypeProp),
(∀ x, P(x)) → (∀ x, Q(x)) → (∀ x, (P(x) ↔ Q(x))).
Proof. firstorder. Qed.