(*************************************************************************)
(** * Exists-Fresh Definitions *)
(*************************************************************************)
(* The use of cofinite quantification may make some people worry that we are not formalizing the "right" language. Below, we show that the "exists-fresh" version of the rules is the same as the cofinite version. *)
(* First, we redefine the language with the exist-fresh version of the rules everywhere. *)
Inductive typing : env -> exp -> typ -> Prop :=
| typing_var : forall E (x : atom) T,
uniq E ->
binds x T E ->
typing E (fvar x) T
| typing_abs : forall E e T1 T2 (x : atom),
x `notin` fv e ->
typing ((x ~ T1) ++ E) (open e x) T2 ->
typing E (abs T1 e) (typ_arrow T1 T2)
| typing_app : forall E e1 e2 T1 T2,
typing E e1 (typ_arrow T1 T2) ->
typing E e2 T1 ->
typing E (app e1 e2) T2.
Inductive value : exp -> Prop :=
| value_abs : forall e T1,
lc (abs T1 e) ->
value (abs T1 e).
Inductive eval : exp -> exp -> Prop :=
| eval_beta : forall e1 e2 T1,
lc (abs T1 e1) ->
value e2 ->
eval (app (abs T1 e1) e2) (open e1 e2)
| eval_app_1 : forall e1 e1' e2,
lc e2 ->
eval e1 e1' ->
eval (app e1 e2) (app e1' e2)
| eval_app_2 : forall e1 e2 e2',
value e1 ->
eval e2 e2' ->
eval (app e1 e2) (app e1 e2').
Hint Constructors typing value eval.
(*************************************************************************)
(** * Equivalence of Exists-Fresh and Cofinite Definitions *)
(*************************************************************************)
(* Next, we prove that these two definitions type the same terms. *)

(** First, we show that the two local closure predicates are equivalent. This lemma follows via a renaming lemma for lc_c. *)
Lemma lc_rename : forall e (x:atom) (y:atom),
x `notin` fv e ->
lc_c (open e x) -> lc_c (open e y).