Fixpoint exn (n:nat) :=
  match n with O => False | S n => exists tt:unit, exn n end.

Goal exn 125 -> False. intro H.
  Time (repeat match goal with H:exn _ |-_=> destruct H end; assumption).
Time Qed.
(* Finished transaction in 0.222 secs (0.161u,0.059s) (successful) *)
(* Finished transaction in 0.105 secs (0.105u,0.s) (successful) *)

Goal exn 250 -> False. intro H. idtac "".
  Time (repeat match goal with H:exn _ |-_=> destruct H end; assumption).
Time Qed.
(* Finished transaction in 0.511 secs (0.505u,0.002s) (successful) *)
(* Finished transaction in 0.389 secs (0.387u,0.s) (successful) *)

Goal exn 500 -> False. intro H. idtac "".
  Time (repeat match goal with H:exn _ |-_=> destruct H end; assumption).
Time Qed.
(* Finished transaction in 2.439 secs (2.41u,0.013s) (successful) *)
(* Finished transaction in 1.776 secs (1.766u,0.s) (successful) *)

Goal exn 1000 -> False. intro H. idtac "".
  Time (repeat match goal with H:exn _ |-_=> destruct H end; assumption).
Time Qed.
(* Finished transaction in 8.632 secs (8.509u,0.066s) (successful) *)
(* Finished transaction in 6.266 secs (6.226u,0.003s) (successful) *)

Goal exn 2000 -> False. intro H. idtac "".
  Time (repeat match goal with H:exn _ |-_=> destruct H end; assumption).
Time Qed.
(* Finished transaction in 33.803 secs (33.401u,0.202s) (successful) *)
(* Finished transaction in 26.069 secs (25.866u,0.049s) (successful) *)

(* coqc destruct_ex_unfold.v  121.45s user 0.58s system 99% cpu 2:02.62 total *)


Require Export Iron.Language.SystemF2Cap.Type.Exp.Base.
Require Export Iron.Language.SystemF2Cap.Type.Relation.WfT.

(********************************************************************)
(* Type Utils *)
(* Construct a type application from a constructor type
   and a list of argument types. *)
Fixpoint makeTApps (t1: ty) (tt: list ty) : ty :=
 match tt with
 | nil     => t1
 | t :: ts => makeTApps (TApp t1 t) ts
 end.

Fixpoint takeTCon (tt: ty) : ty :=
 match tt with
 | TApp t1 t2 => takeTCon t1
 | _          => tt
 end.

Fixpoint takeTArgs (tt: ty) : list ty :=
 match tt with
 | TApp t1 t2 => snoc t2 (takeTArgs t1)
 | _          => cons tt nil
 end.

(* Break apart a type application into the constructor type
   and a list of argument types. *)
Definition takeTApps (tt: ty) : (ty * list ty)
 := (takeTCon tt, takeTArgs tt).

(* Take the region identifier from an effect, if any. *)
Fixpoint rgnOfEffect (e : ty) : option nat :=
 match e with
 | TCon1 tc (TRgn p)  => if isEffectTyCon_b tc then Some p else None
 | _                  => None
 end.

(* Take the variable from an effect, if any. *)
Fixpoint varOfEffect (e : ty) : option nat :=
 match e with
 | TCon1 tc (TVar n)  => if isEffectTyCon_b tc then Some n else None
 | _                  => None
 end.

(********************************************************************)
Lemma makeTApps_snoc
 : forall t1 t2 t3 ts
 , makeTApps (TApp t1 t2) (snoc t3 ts)
 = TApp (makeTApps t1 (cons t2 ts)) t3.
Proof.
 intros. gen t1 t2.
 induction ts; burn.
Qed.

Lemma makeTApps_snoc'
 :  forall t1 t2 ts
 ,  makeTApps t1 (snoc t2 ts)
 =  TApp (makeTApps t1 ts) t2.
Proof.
 intros. gen t1 t2.
 induction ts; burn.
Qed.

Lemma takeTCon_makeTApps
 :  forall t1 ts
 ,  takeTCon (makeTApps t1 ts) = takeTCon t1.
Proof.
 intros. gen t1.
 induction ts; rip; burn.
 simpl. rewritess. burn.
Qed.
Hint Resolve takeTCon_makeTApps.

Lemma makeTApps_takeTCon
 :  forall t1 t2 ts
 ,  makeTApps t1 ts = t2
 -> takeTCon t1     = takeTCon t2.
Proof.
 intros. gen t1 t2.
 induction ts; intros.
 - simpl in H. subst. auto.
 - eapply IHts in H. simpl in H. auto.
Qed.
Hint Resolve makeTApps_takeTCon.

Lemma makeTApps_rewind
 :  forall t1 t2 ts
 ,  makeTApps (TApp t1 t2) ts
 =  makeTApps t1 (t2 :: ts).
Proof. burn. Qed.

(* A type application constructed from well formed components is
   itself well formed. *)
Lemma makeTApps_wfT
 :  forall n t1 ts
 ,  WfT n t1
 -> Forall (WfT n) ts
 -> WfT n (makeTApps t1 ts).
Proof.
 intros. gen t1.
 induction ts; intros.
 - simpl. auto.
 - simpl.
   inverts H0.
   have HS: (ts = nil \/ (exists t ts', ts = t <: ts'))
    by (apply snocable).
   inverts HS.
   + simpl. auto.
   + dest H0. dest H0. subst.
     eapply IHts; auto.
Qed.

Lemma rgnOfEffect_form_some
 :  forall e p
 ,  rgnOfEffect e = Some p
 -> exists tc
     ,  e    = TCon1 tc (TRgn p)
     /\ true = isEffectTyCon_b tc.
Proof.
 intros.
 destruct e; snorm.
 - destruct e; snorm.
   destruct t0; snorm.
   exists t. rip.
 - destruct e; snorm.
   destruct t0; snorm.
Qed.
Hint Resolve rgnOfEffect_form_some.