WtypesInCoq - coq/coq GitHub Wiki

(** * Primitives constructions of W_types *)
(** ** Definition of W_trees for the recursivity *)
Inductive W_tree
         (constructeur : Type)
         (parametre: constructeur -> Type)
         : Type :=
W_acc: forall (cons: constructeur)
              (pars: parametre cons -> W_tree constructeur parametre),
              W_tree constructeur parametre.
(** ** Definition of empty type to have leaves in W_trees *)
Inductive Empty: Type :=.
(** ** Definition of the binary sum to have a type with at least two constructors *)
Inductive BinarySum (A: Type) (B: Type): Type :=
| Left: A -> BinarySum A B
| Right: B -> BinarySum A B.
(** ** Definition of the dependant sum for existentials *)
Inductive DependantSum (A: Type) (f: A -> Type): Type :=
| Exist: forall a, f a -> DependantSum A f.
(** ** Definition of the dependant products for universals *)
Inductive DependantProduct (A: Type) (f: A -> Type) :=
| Forall: (forall a, f a) -> DependantProduct A f.
(** * Given a type, we have a predicate to tell if it is a W_type one *)
Inductive WTYPE: Type -> Prop :=
| WW_tree: forall C P, WTYPE C -> (forall c, WTYPE (P c)) -> WTYPE (W_tree C P)
| WEmpty: WTYPE Empty
| WBSum: forall A B, WTYPE A -> WTYPE B -> WTYPE (BinarySum A B)
| WDSum: forall A f, WTYPE A -> (forall a, WTYPE (f a)) ->
         WTYPE (DependantSum A f)
| WProduct: forall A f, WTYPE A -> (forall a, WTYPE (f a)) ->
            WTYPE (DependantProduct A f).
(** * Now, we require extensionnality to build w_types such as natural numbers *)
Axiom ext: forall A B (f g: A -> B),
 (forall a, f a = g a) -> g = f.
Ltac cext H := case (ext _ _ _ _ H).
(** * A cast from empty type to any other *)
Definition Leaf (T: Type) (a: Empty): T := match a with end.
Lemma Leaf_elim: forall (A: Type) (f g: Empty -> A), g = f.
Proof.
 intros A f g.
 apply ext; intros [].
Qed.
(** Now, w_types are fully defined.
 Next section presents some examples. *)
(** * Some well known types seen as w_types *)
(** ** Unit type *)
Definition Unit := DependantProduct Empty (fun _ => Empty).
Lemma WUnit: WTYPE Unit.
Proof WProduct _ _ WEmpty (Leaf (WTYPE Empty)).
Definition single: Unit := Forall _ _ (Leaf Empty).
Lemma all_unit_is_single: forall u, single = u.
Proof.
 intros u; destruct u.
 case (Leaf_elim _ e (Leaf Empty)).
 split.
Qed.
(** ** Booleans type *)
Definition Bool := BinarySum Unit Unit.
Lemma WBool: WTYPE Bool.
Proof WBSum _ _ WUnit WUnit.
Definition top: Bool := Left _ _ single.
Definition bottom: Bool := Right _ _ single.
Definition Ift (A B: Type) (t: Bool): Type :=
if t then A else B.
Definition If (A B: Type) (P: Type -> Type) (Pt: P A) (Pb: P B)
              (t: Bool): P (Ift A B t) :=
if t as t0 return P (Ift A B t0)
   then Pt
   else Pb.
(** ** Naturals type *)
Definition Nat := W_tree Bool (Ift Empty Unit).
Lemma WNat: WTYPE Nat.
Proof WW_tree _ _ WBool (If _ _ _ WEmpty WUnit).
Definition O: Nat := W_acc _ _ top (Leaf _).
Definition S (n: Nat) : Nat := W_acc _ _ bottom (fun _ => n).
Lemma Nat_ind: forall (P : Nat -> Prop), P O -> (forall n, P n -> P (S n)) ->
forall n, P n.
 induction n.
 destruct cons; simpl in *.
  case (Leaf_elim _ pars (Leaf Nat)).
  case (all_unit_is_single u).
  assumption.
 unfold S in H0.
 case (all_unit_is_single u).
 assert (K := H0 _ (H1 single)); clear H0; simpl in K.
 assert ((fun _ : Unit => pars single) = pars).
  apply ext; intro a; case (all_unit_is_single a); split.
 case H0; assumption.
Qed.
(** ** And eventually parametric lists type *)
Definition List (A : Type) := W_tree (BinarySum Unit A)
                (fun b => if b then Empty else Unit).
Lemma WList: forall A, WTYPE A -> WTYPE (List A).
Proof.
 intros A WA; apply WW_tree.
  apply WBSum.
   exact WUnit.
  exact WA.
 intros []; intro.
  exact WEmpty.
 exact WUnit.
Qed.
Definition Nil A : List A := W_acc _ _ (Left _ _ single) (Leaf _).
Definition Cons A (a: A) (l: List A): List A :=
 W_acc _ _ (Right _ _ a) (fun _ => l).