Library exercises

Preliminaries

Instructor's Name: Jason Username: espuser Password: !Splash2014
How to install Coq: Open up a terminal, and type
    tellme root
    sudo apt-get install coq coqide emacs proofgeneral-coq
At home, you can download it from https://coq.inria.fr/.
You can download this file from: http://web.mit.edu/jgross/Public/2014-splash/equality/exercises.v

Warmup - Getting used to Coq

Let's see how to prove some things. You may find http://andrej.com/coq/cheatsheet.pdf helpful.
Here's a partial list:
  • simpl simplifies things
  • compute shows you the normal form
  • intro x
  • destruct x, case x, induction x do case analysis on x
  • reflexivity proves a goal of the form x = x
  • apply H makes use of a hypothesis H
  • rewrite H replaces x with y when H is of type x = y
  • rewrite <- H replaces y with x when H is of type x = y
  • split is used to prove _ _ (conjunction)
  • left and right are used to prove _ _ (disjunction)
Section WarmUp.
We use a cheating axiom as a placeholder. Your code should not end with any admits. We use curly braces to not have to give T explicitly.
  Axiom admit : {T}, T.

  Lemma id' : A, AA.
  Proof.
    admit.
  Defined.

  Print id'.

  Definition id : A, AA
    := admit.

  Lemma compose' : A B C, (AB) → (BC) → (AC).
  Proof.
    admit.
  Defined.

  Print compose'.

  Definition compose {A B C} (g : BC) (f : AB) : AC
    := admit.

  Goal 1 + 1 = 2.
  Proof.
    admit.
  Defined.

  Lemma and_ex : 1 = 1 2 = 2.
  Proof.
    admit.
  Defined.

  Lemma or_ex : 1 = 1 1 = 2.
  Proof.
    admit.
  Defined.

  Lemma or_l : A B : Prop, AA B.
  Proof.
    admit.
  Defined.

  Lemma or_r : A B : Prop, BA B.
  Proof.
    admit.
  Defined.

End WarmUp.

We begin by defining equality:
Inductive eq {A : Type} (x : A) : AType
  := refl : x = x where "x = y" := (@eq _ x y) : type_scope.
Arguments refl {A} x, {A x}.
Notation "x <> y" := (x = yFalse) : type_scope.
This says the following:
  • To ask the question, "is x equal to y?", x and y must both have the same type A.
  • The only way to construct a proof of equality is by reflexivity, which proves, for all x, that x = x.
  • The way to make use of an equality e : x = y is to replace y with x and e with refl. This is formalized in eq_rect:

Check eq_rect.
 eq_rect
     : forall (A : Type) (x : A) (P : forall a : A, x = a -> Type),
       P x refl -> forall (y : A) (e : x = y), P y e
This says that if you are trying to prove P y e for any y : A and e : x = y, it sufficies to prove P x refl, i.e., it sufficies to replace y with x and e with refl and prove the resulting statement.
Using the tactic destruct e or induction e will perform this step in a proof.
Furthermore, there is a computation rule, which says that when y is already x and e is already refl, the eq_rect disappears from your proof, and the resulting term of type P y e *is* the same as the term of type P x refl.
Let's see that this obeys our intuitions.
Section WarmUpEq.
You'll want to use case or destruct here, to do case analysis on the "proof of False". (Hint: There are no proofs of False. So if you have one, you can do trivial case analysis, and there are no cases.)
  Lemma absurd : A, FalseA.
  Proof.
    admit.
  Defined.

  Lemma all_absurd' : ( B, B) → False.
  Proof.
    admit.
  Defined.

  Lemma all_absurd : ( A B, AB) → False.
  Proof.
    admit.
  Defined.

  Lemma all_1p1_eq_2 x (H : 1 = x) : x + x = 2.
  Proof.
    admit.
  Defined.

  Lemma eq_x_true_any A B (x : bool) (H : x = true)
  : Aif x then A else B.
  Proof.
    admit.
  Defined.

  Lemma eq_false_x_any A B (x : bool) (H : false = x)
  : (if x then A else B) → B.
  Proof.
    admit.
  Defined.

  Lemma eq_false_true_any' (H : false = true)
  : A B, AB.
  Proof.
    admit.
  Defined.

  Lemma neq_false_true : false true.
  Proof.
    admit.
  Defined.
End WarmUpEq.

Let's prove some simple lemmas.
Definition sym {A} {x y : A} (e : x = y) : y = x.
Proof.
  admit.
Defined.
Print sym.

We make a notation, so that sym e can be written e^ or e⁻¹. Switch the order of these if you want it to display as e^.
Notation "e ^" := (sym e) (at level 10, format "e '^'").
Notation "e ⁻¹" := (sym e) (at level 10, format "e '⁻¹'").

Definition trans {A} {x y z : A} (p : x = y) (q : y = z) : x = z.
Proof.
  admit.
Defined.

We make another notation for trans, which can be thought of as concatenating or composing equality proofs.
Notation "p @ q" := (trans p q) (at level 20, left associativity).
Notation "p • q" := (trans p q) (at level 20, left associativity).

When are two proofs of equality themselves equal? Since refl proves x = x, we have that any proof of equality is equal to itself.

Definition eq_refl_refl : A (x : A), refl x = refl x
  := admit.

Our computation rules also give us that refl⁻¹ = refl and refl refl = refl.
Definition sym_refl {A} (x : A) : (refl x)^ = refl x.
Proof.
unfold sym
  cbv delta [sym].
plug arguments into functions
  cbv beta.
compute pattern matches
  cbv iota.
  admit.
Defined.

Definition trans_refl {A} (x : A) : refl x @ refl x = refl x.
Proof.
  admit.
Defined.

Definition ap {A B} (f : AB) {x y : A} : x = yf x = f y.
Proof.
  admit.
Defined.

We can prove the following in two different ways: By doing case analysis on b1 then b2, or by doing case analysis on b2 then b1.
N.B. There are more ways to prove this theorem, which might not all be equal.
Definition bool_case_1 : b1 b2 : bool, b1 = b2 b1 = true b2 = true.
Proof.
  intros b1 b2.
  case b1, b2.
  { admit. }
  { admit. }
  { admit. }
  { admit. }
Defined.

Definition bool_case_2 : b1 b2 : bool, b1 = b2 b1 = true b2 = true.
Proof.
  intros b1 b2.
  case b2, b1.
  { admit. }
  { admit. }
  { admit. }
  { admit. }
Defined.

We can prove that these two proofs are equal, by case analysis on b1 and b2.
Definition bool_case_eq : b1 b2, bool_case_1 b1 b2 = bool_case_2 b1 b2.
Proof.
  intros b1 b2.
  unfold bool_case_1, bool_case_2.
  case b1, b2.
  { admit. }
  { admit. }
  { admit. }
  { admit. }
Defined.

We can, in fact, prove this in another way, too.
Definition bool_case_eq' : b1 b2, bool_case_1 b1 b2 = bool_case_2 b1 b2.
Proof.
  intros b1 b2.
  unfold bool_case_1, bool_case_2.
  case b2, b1.
  { admit. }
  { admit. }
  { admit. }
  { admit. }
Defined.

And we can prove that these two ways are equal...
Definition bool_case_eq_eq : b1 b2, bool_case_eq b1 b2 = bool_case_eq' b1 b2.
Proof.
  intros b1 b2.
  unfold bool_case_eq, bool_case_eq'.
  case b1, b2.
  { admit. }
  { admit. }
  { admit. }
  { admit. }
Defined.

What other properties can we prove?
Definition sym_sym {A} (x y : A) (e : x = y) : (e^)^ = e.
Proof.
  admit.
Defined.

Definition trans_1p {A} {x y : A} (e : x = y) : refl @ e = e.
Proof.
  admit.
Defined.

Definition trans_p1 {A} {x y : A} (e : x = y) : e @ refl = e.
Proof.
  admit.
Defined.

Definition trans_assoc {A} {x y z w : A} (p : x = y) (q : y = z) (r : z = w)
: (p @ q) @ r = p @ (q @ r).
Proof.
  admit.
Defined.

Definition trans_pV {A} (x y : A) (p : x = y) : p @ p^ = refl.
Proof.
  admit.
Defined.

Definition trans_Vp {A} (x y : A) (p : x = y) : p^ @ p = refl.
Proof.
  admit.
Defined.

Definition trans_sym {A} (x y z : A) (p : x = y) (q : y = z)
: (p @ q)^ = q^ @ p^.
Proof.
  admit.
Defined.

There are also rules for how ap plays with trans and sym. Try to state and prove them.
Definition ap_sym {A B} (f : AB) {a b : A} (p : a = b)
: admit.
Proof.
  admit.
Defined.

Definition ap_trans {A B} (f : AB) {a b c : A} (p : a = b) (q : b = c)
: admit.
Proof.
  admit.
Defined.

Now back to the rules not involving ap.

Definition whisker_l {A} {x y z : A} (r : x = y) {p q : y = z} (w : p = q)
: r @ p = r @ q.
Proof.
  admit.
Defined.

Definition whisker_r {A} {x y z : A} {p q : x = y} (w : p = q) (r : y = z)
: p @ r = q @ r.
Proof.
  admit.
Defined.

Notation "r @L w" := (whisker_l r w) (at level 20).
Notation "r •ˡ w" := (whisker_l r w) (at level 20).
Notation "w @R r" := (whisker_r w r) (at level 20).
Notation "w •ʳ r" := (whisker_r w r) (at level 20).

We can relate trans_1p, trans_p1, and trans_assoc in a commutative triangle:
    (p • refl) • q == p • (refl • q)
           \\          //
             \\      //
               \\  //
                p • q
Definition triangle_leg_1 {A} {x y z : A} (p : x = y) (q : y = z)
: (p @ refl) @ q = p @ (refl @ q)
  := trans_assoc _ _ _.
Definition triangle_leg_2 {A} {x y z : A} (p : x = y) (q : y = z)
: p @ (refl @ q) = p @ q
  := p @L trans_1p q.
Definition triangle_leg_3 {A} {x y z : A} (p : x = y) (q : y = z)
: (p @ refl) @ q = p @ q
  := trans_p1 p @R q.
Definition triangle {A} {x y z : A} (p : x = y) (q : y = z)
: triangle_leg_1 p q @ triangle_leg_2 p q = triangle_leg_3 p q.
Proof.
  unfold triangle_leg_1, triangle_leg_2, triangle_leg_3.
  admit.
Defined.

There is a similar pentagon relating the two different ways of proving that p @ (q @ (r @ s)) = ((p @ q) @ r) @ s using chains of trans_assoc.
Write down the five legs of this pentagon, and prove that the two paths are equal.
  ((p @ q) @ r) @ s ======= (p @ (q @ r)) @ s
          ||                    ||
          ||                    ||
          ||                    ||
   (p @ q) @ (r @ s)         p @ ((q @ r) @ s)
          \\                   //
            \\               //
              \\           //
                \\       //
             p @ (q @ (r @ s))
Definition pentagon {A} {a b c d e : A} (p : a = b) (q : b = c) (r : c = d) (s : d = e)
: admit.
Proof.
  admit.
Defined.

There are higher dimensional rules, too, that relate the triangle and the pentagon. They are known as Stasheff polyhedra or associahedra.
Let's look at more complicated things.
We can proof that all proofs of False are equal
Hint 1: There are no such proofs.
Hint 2: You can use exfalso to say "it sufficies to prove False".
Lemma all_eq_False : x y : False, x = y.
Proof.
  admit.
Defined.

Lemma all_eq_eq_False : (x y : False) (p q : x = y), p = q.
Proof.
  admit.
Defined.

We can prove that all proofs of false = true are equal.

Lemma all_eq_false_true : p q : false = true, p = q.
Proof.
  admit.
Defined.

We can proof that all proofs of equality of things of type unit are equal, but we need to prove something more general.
Print unit.
It sufficies to prove that all x : unit are equal to tt. To do this, we need to construct a canonical proof of tt = x for all x.
Lemma unit_canonical_proof : x : unit, tt = x.
Proof.
  admit.
Defined.

Lemma eq_unit_tt {x : unit} (p : tt = x) : p = unit_canonical_proof x.
Proof.
  admit.
Defined.

Note: to see the result of applying a theorem to an argument, you can use pose proof (thm args) as H.
Lemma UIP_tt : p : tt = tt, p = refl.
Proof.
  admit.
Defined.

Lemma UIP_unit {x : unit} : p : x = x, p = refl.
Proof.
  admit.
Defined.

It is possible to prove that all proofs of true = true are equal, but we have to prove a more general theorem. Namely, we need to prove a fact for all b : bool and p : true = b at once. In the case that b is true, we prove that p = refl. In the case that b is false, we prove absurdity (False).
Definition eq_true_canonical_proof {b : bool} (p : true = b)
: match b as b' return true = b'Prop with
    | truefun p'p' = refl
    | falsefun _False
  end p.
Proof.
  admit.
Defined.

UIP stands for "uniqueness of identity proofs".
Definition UIP_true_true (p : true = true) : p = refl.
Proof.
  admit.
Defined.

More generally, we can prove uniqueness of identity proofs for booleans.
Definition eq_bool_canonical_proof {b1 b2 : bool} (p : b1 = b2)
: match b1 as b1', b2 as b2' return b1' = b2'Prop with
    | true, truefun p'p' = refl
    | false, falsefun p'p' = refl
    | true, falsefun _False
    | false, truefun _False
  end p.
Proof.
  admit.
Defined.

Definition UIP_bool {b1 b2 : bool} : p q : b1 = b2, p = q.
Proof.
  admit.
Defined.

It is possible to prove that UIP goes up levels.
Lemma UIP_bump_helper {A} {x y : A}
      (UIP_A : (p q : x = y), p = q)
      (UIP_A_comp : (p : x = y), UIP_A p p = refl)
: (p q : x = y) (T U : p = q), T = U.
Proof.
  admit.
Defined.

Definition UIP_adjust {A} {x y : A} (H : (p q : x = y), p = q)
           (p q : x = y)
: p = q.
Proof.
  admit.
Defined.

Lemma UIP_bump {A} {x y : A}
      (UIP_A : (p q : x = y), p = q)
: (p q : x = y) (T U : p = q), T = U.
Proof.
  admit.
Defined.

Can you prove this in general? We can try to ask: "Are all proofs of equality equal to reflexivity?" But this question does not typecheck. There are subtle reasons for this, and it ends up being important.
Fail Check A (x y : A) (p : x = y), p = refl.

We can instead try to prove that any proof of x = x is refl.
Lemma UIP : {A} {x : A} (p : x = x), p = refl.
Proof.
  admit.
Defined.