Chapter 3 - Definitional Equality and Propositional Equality


Require Import Base.
Require Import Omega.
Set Implicit Arguments.
Unset Strict Implicit.

3.1 Conversion Principle


Goal ~~True.
Proof.
  change (¬True → False).
  change (~(True → False)).
  change (~~True).
  hnf.
  change (~~True).
  cbv.
  change (~~True).
  simpl.
  pattern True.
  pattern not at 2.
  hnf.
  exact (fun f ⇒ f I).
  Show Proof.
Qed.

Inductive demo (X : Type) (x : X) : Prop :=
| demoI : demo x.

Goal demo plus.
Proof.
  unfold plus.
  unfold plus.
  fold plus.
  apply demoI.
Qed.

Goal demo (fun x : nat ⇒ x).
Proof.
  change (demo (fun y : nat ⇒ y)).
  change (demo (fun myname : nat ⇒ myname)).
  apply demoI.
Qed.

Section Demo.
  Variable n : nat.

  Goal demo (5+n+n).
  Proof.
    change (demo (2+3+n+n)).
    simpl.
    change (demo (10+n-5+n)).
    pattern n at 1.
    hnf.
    simpl.
    apply demoI.
  Qed.

  Variable X : Type.
  Variable f : X → X → X.

  Goal demo f.
  Proof.
    change (demo (fun x ⇒ f x)).
    cbv.
    change (demo (fun x y ⇒ f x y)).
    cbv.
    apply demoI.
  Qed.

End Demo.

3.2 Disjointness and Injectivity of Constructors


Goal false ≠ true.
Proof.
  intros A.
  change (if false then True else False).
  rewrite A.
  exact I.
Qed.

Lemma disjoint_O_S n :
  0 ≠ S n.
Proof.
  intros A.
  change (match 0 with 0 ⇒ False | _ ⇒ True end).
  rewrite A.
  exact I.
Qed.

Lemma injective_S x y :
  S x = S y → x = y.
Proof.
  intros A.
  change (pred (S x) = pred (S y)).
  rewrite A.
  reflexivity.
Qed.

Goal ∀ x, S x ≠ 0.
Proof. intros x A. discriminate A. Qed.

Goal ∀ x y, S x = S y → x = y.
Proof. intros x y A. injection A. auto. Qed.

(* Exercise 3.2.1 *)
Goal ∀ (X: Type) (x:X),
       Some x ≠ None.
Abort.

Goal ∀ (X: Type) (x: X) (A: list X),
       x :: A ≠ nil.
Abort.

(* Exercise 3.2.2 *)
Goal ∀ (X Y: Type) (x x' : X) (y y' : Y),
       (x,y) = (x',y') → x=x' ∧ y = y'.
Abort.

Goal ∀ (X : Type) (x x' : X) (A A' : list X),
       x::A = x'::A' → x=x' ∧ A = A'.
Abort.

(* Exercise 3.2.3 *)
Goal ∀ x, negb x ≠ x.
Abort.

Goal ∀ x, S x ≠ x.
Abort.

Goal ∀ x y z, x + y = x + z → y = z.
Abort.

Goal ∀ x y : nat, x = y ∨ x ≠ y.
Abort.

(* Exercise 3.2.4 *)
Goal ∃ (X : Type) (f : list X → X), ∀ A B, f A = f B → A = B.
Abort.

(* Exercise 3.2.5 *)
Goal False ≠ True.
Abort.

(* Exercise 3.2.6 *)
Goal ∃ (f : nat → nat → nat) x,
       (fun x ⇒ f x x) ≠ f x.
Abort.

3.3 Leibniz Equality


Definition leibniz_eq (X : Type) (x y : X) : Prop :=
  ∀ p : X → Prop, p x → p y.

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

Lemma leibniz_refl X (x : X) :
  x == x.
Proof. hnf. auto. Qed.

Lemma leibniz_sym X (x y : X) :
  x == y → y == x.
Proof.
  unfold leibniz_eq. intros A p.
  apply (A (fun z ⇒ p z → p x)).
  auto.
Qed.

Lemma leibniz_agrees X (x y : X) :
  x == y ↔ x = y.
Proof.
  split ; intros A.
  - apply (A (fun z ⇒ x=z)). reflexivity.
  - rewrite A. apply leibniz_refl.
Qed.

Lemma leibniz_rewrite X (x y : X) (p : X → Prop) :
  x == y → p y → p x.
Proof. intros A. apply (leibniz_sym A). Qed.

Lemma leibniz_plus_assoc x y z :
  (x + y) + z == x + (y + z).
Proof.
  induction x ; simpl.
  - apply leibniz_refl.
  - pattern (x+y+z). apply (leibniz_rewrite IHx). apply leibniz_refl.
Qed.

(* Exercise 3.3.1 *)
Goal ∀ x y, x + y == y + x.
Abort.

(* Exercise 3.3.2 *)
Lemma leibniz_rewrite_lr X (x y : X) (p : X → Prop) :
  x == y → p y → p x.
Abort.

Lemma leibniz_rewrite_rl X (x y : X) (p : X → Prop) :
       x == y → p x → p y.
Abort.

3.4 By Name Specification of Implicit Arguments


About leibniz_sym.

Goal ∀ X (x y : X) (p : X → Prop),
       x == y → p y → p x.
Proof.
  intros X x y p A.
  Check leibniz_sym A.
  Check leibniz_sym A (p:=p).
  Check @leibniz_sym X x y A p.
  Check @leibniz_sym _ _ _ A p.
  exact (leibniz_sym A (p:=p)).
  Show Proof.
Qed.

3.5 Local Definitions


Compute let x := 2 in x + x.

Compute let x := 2 in let x := x + x in x.

Compute let f := plus 3 in f 7.

Check let X := nat in (fun x : X ⇒ x) 2.

(* This check is supposed to result in an error:
Check (fun X => (fun x : X => x) 2) nat.
*)


3.6 Proof of nat <> bool


Goal bool ≠ nat.
Proof.
  pose (p X := ∀ x y z : X, x=y ∨ x=z ∨ y=z).
  assert (H: ¬p nat).
  { intros B. specialize (B 0 1 2). destruct B as [B|[B|B]] ; discriminate B. }
  intros A. apply H. rewrite <- A.
  intros [|] [|] [|] ; auto.
Qed.

(* Exercise 3.6.1 *)
Goal bool ≠ option bool.
Abort.

Goal option bool ≠ prod bool bool.
Abort.

Goal bool ≠ False.
Abort.

3.7 Cantor's Theorem


Definition surjective (X Y : Type) (f : X → Y) : Prop := ∀ y, ∃ x, f x = y.

Lemma Cantor X :
  ¬ ∃ f : X → X → Prop, surjective f.
Proof.
  intros [f A].
  pose (g x := ¬ f x x).
  specialize (A g).
  destruct A as [x A].
  assert (H: ¬ (g x ↔ ¬ g x)) by tauto.
  apply H. unfold g at 1. rewrite A. tauto.
Qed.

(* Exercise 3.7.1 *)

Goal ¬ ∃ f : nat → nat → nat, surjective f.
Abort.

Goal ¬ ∃ f : bool → bool → bool, surjective f.
Abort.

(* Exercise 3.7.2 *)

Lemma Cantor_generalized X Y :
  (∃ N : Y → Y, ∀ y, N y ≠ y) →
  ¬ ∃ f : X → X → Y, surjective f.
Abort.

(* Exercise 3.7.3 *)

Lemma Cantor_neq X Y (f : X → X → Y) (N : Y → Y) :
 (∀ y, N y ≠ y) → ∃ h, ∀ x, f x ≠ h.
Abort.

(* Exercise 3.7.4 *)

Definition injective (X Y : Type) (f : X → Y) : Prop := ∀ x x' : X, f x = f x' → x = x'.

Goal ∀ X Y : Type, ∀ f : X → Y, (∃ g : Y → X, ∀ y, f (g y) = y) → surjective f.
Abort.

Goal ∀ X Y : Type, ∀ f : X → Y, (∃ g : Y → X, ∀ x, g (f x) = x) → injective f.
Abort.

(* Exercise 3.7.5 *)

Goal ∀ X, ¬ ∃ f : (X → Prop) → X, injective f.
Proof.
  intros X [f A].
  pose (p x := ∃ h, f h = x ∧ ¬ h x).
  (* ... *)
Abort.

3.8 Kaminski's Equation


Goal ∀ (f : bool → bool) (x : bool), f (f (f x)) = f x.
Proof. intros f x. destruct x, (f true) eqn:A, (f false) eqn:B ; congruence. Qed.

Lemma destruct_eqn_bool (p : bool → Prop) (x : bool) :
  (x = true → p true) → (x = false → p false) → p x.
Proof. destruct x ; auto. Qed.

Goal ∀ (f : bool → bool) (x : bool), f (f (f x)) = f x.
Proof.
  destruct x ;
  pattern (f true) ; apply destruct_eqn_bool ;
  pattern (f false) ; apply destruct_eqn_bool ;
  congruence.
Qed.

(* Exercise 3.8.1 *)

Goal ∀ (f g : bool → bool) (x : bool), f (f (f (g x))) = f (g (g (g x))).
Abort.

3.9 Boolean Equality Tests


Fixpoint nat_eqb (x y : nat) : bool :=
  match x, y with
    | O, O ⇒ true
    | S x', S y' ⇒ nat_eqb x' y'
    | _, _ ⇒ false
  end.

Lemma nat_eqb_agrees x y :
  nat_eqb x y = true ↔ x = y.
Proof.
  revert y.
  induction x ; intros [|y] ; split ; simpl ; intros A ; try congruence.
  - f_equal. apply IHx, A.
  - apply IHx. congruence.
Qed.

(* Exercise 3.9.1 *)

(* Definition bool_eqb (x y: bool) : bool :=
 (* ... *) *)


(* Exercise 3.9.2 *)

(* Fixpoint list_eqb (X: Type) (X_eqb: X -> X -> bool) (A B: list X) :=
 (* ... *)

Lemma list_eqb_agrees X (X_eqb : X -> X -> bool) (A B : list X) :
  (forall x y, X_eqb x y = true <-> x = y) ->
  (list_eqb X_eqb A B = true <-> A = B). *)