FixpointFiniteTypes - coq/coq GitHub Wiki

    Require Image.
    Require Import List.
    Set Implicit Arguments.
    Fixpoint Fin (n:nat) : Set :=
    match n with
    | O => Empty_set
    | (S m) => (unit+(Fin m))%type
    end.
    Definition FinNew (n:nat) : Fin (S n) := inl (Fin n) tt.
    Definition FinOld (n:nat) (x:Fin n) : Fin (S n) := inr unit x.
    Implicit Arguments FinOld [n].
    Lemma FinO_rect : forall P:Type, Fin O -> P.
    Proof.
    destruct 1.
    Defined.
    Lemma FinSn_rect :
     forall n,
     forall (P:Fin (S n)->Type),
     (forall y:Fin n, P (FinOld y)) ->
     P (FinNew n) ->
     forall x, P x.
    Proof.
    intros n P H0 H1 [[]|]; auto.
    Defined.
    Lemma FinOldOrNew : forall n,
    forall y:Fin (S n),
    {z:Fin n | y=(FinOld z)}+{y=FinNew n}.
    Proof.
    intros n [[]|y]; auto.
    left.
    exists y; auto.
    Defined.
    Lemma FinOldInject : forall n, forall x y:Fin n, (FinOld x)=(FinOld y) -> x=y.
    Proof.
    intros n x y H.
    unfold FinOld in H.
    congruence.
    Qed.
    Hint Resolve FinOldInject : fin.
    Lemma FinDecideEquality : forall n, forall (x y:Fin n), {x=y}+{x<>y}.
    Proof.
    induction n.
    destruct x.
    simpl.
    intros [[]|x] [[]|y]; auto; try (right; discriminate).
    destruct (IHn x y).
    left; intuition; congruence.
    right; intuition; congruence.
    Defined.
    Lemma FinForallOrExist : forall n
    (P Q:Fin n->Prop),
    (forall x, {P x}+{Q x}) ->
    {x:Fin n | P x}+{forall x, Q x}.
    Proof.
    induction n.
    intros P Q H.
    right.
    destruct x.
    intros P Q H.
    destruct (H (FinNew n)).
    left.
    exists (FinNew n); auto.
    destruct (IHn (fun x=>(P (FinOld x)))
                  (fun x=>(Q (FinOld x)))
                  (fun x=> (H (FinOld x)))).
    destruct s.
    left.
    exists (FinOld x); auto.
    right.
    intros [[]|x]; firstorder.
    Defined.
    Definition FinList : forall n, {l:list (Fin n) | forall x, In x l}.
    intros.
    induction n.
    exists (@nil (Fin 0)).
    destruct x.
    destruct IHn.
    exists (cons (FinNew n) (map (@FinOld n) x)).
    intros [[]|y]; simpl; auto.
    right.
    change (In (FinOld y) (map (FinOld (n:=n)) x)).
    apply in_map; auto with *.
    Defined.
    Lemma FinInjectionInjection : forall n m, forall f:Fin (S n) -> Fin (S m), Image.injective _ _ f -> {g:Fin n -> Fin m | Image.injective _ _ g}.
    Proof.
    intros n m f H.
    destruct (FinOldOrNew (f (FinNew n))).
    destruct s.
    exists (fun a:Fin n=>
    match (FinOldOrNew (f (FinOld a))) with
    | inleft p => proj1_sig p
    | inright _ => x
    end).
    intros a b A.
    destruct (FinOldOrNew (f (FinOld a))); try destruct s;
    destruct (FinOldOrNew (f (FinOld b))); try destruct s;
    simpl in A.
    apply FinOldInject.
    apply H.
    congruence.
    assert ((FinOld a)=(FinNew n)).
    apply H.
    congruence.
    discriminate H0.
    assert ((FinOld b)=(FinNew n)).
    apply H.
    congruence.
    discriminate H0.
    apply FinOldInject.
    apply H.
    congruence.
    assert (forall x, {y:Fin m | f (FinOld x) = FinOld y}).
    intros x.
    destruct (FinOldOrNew (f (FinOld x))).
    auto.
    assert ((FinNew n)=(FinOld x)).
    apply H.
    congruence.
    discriminate H0.
    exists (fun x=>(proj1_sig (H0 x))).
    intros a b A.
    destruct (H0 a).
    destruct (H0 b).
    simpl in A.
    apply FinOldInject.
    apply H.
    congruence.
    Defined.
    Lemma FinInjectionLt : forall n m, forall f:Fin n -> Fin m, Image.injective _ _ f -> n <= m.
    Proof.
    induction n; auto with *.
    destruct m.
    intro f.
    destruct (f (FinNew n)).
    intros f H.
    apply Le.le_n_S.
    destruct (FinInjectionInjection H).
    firstorder.
    Qed.