(*************************************************************************)
(** * 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. *)

(* Specifications: *)
(** 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).
(* Demo: the next set of proofs are straightforward, so they are amenable to a fair amount of automation. Step through the demos, then follow the pattern in the take home exercises to practice with simple proof automation. *)
Lemma lc_to_lc_c : forall e, lc e -> lc_c e.
(* Take-home exercise. *)
Lemma lc_c_to_lc : forall e, lc_c e -> lc e.
(** Correspondence of typing and typing_c *)
(* Demo. Again only the abs case is tricky. *)
Lemma typing_to_typing_c : forall E e T,
typing E e T -> typing_c E e T.
(* Take-home exercise. *)
Lemma typing_c_to_typing : forall E e T,
typing_c E e T -> typing E e T.
(* Demo. The pattern [eauto using lemma] is a powerful way to completely automate all of the cases of a simple proof. *)
Lemma value_to_value_c : forall e,
value e -> value_c e.
(* Take-home exercise: Try to do the same for the following lemma. *)
Lemma value_c_to_value : forall e,
value_c e -> value e.
(* Demo: We can do the same trick with several lemmas. *)
Lemma eval_to_eval_c : forall e e',
eval e e' -> eval_c e e'.
(* Take-home exercise. *)
Lemma eval_c_to_eval : forall e e',
eval_c e e' -> eval e e'.
Lemma preservation : forall E e e' T,
typing E e T ->
eval e e' ->
typing E e' T.
Lemma progress : forall e T,
typing nil e T ->
value e \/ exists e', eval e e'.
(** 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).
(* Demo: the next set of proofs are straightforward, so they are amenable to a fair amount of automation. Step through the demos, then follow the pattern in the take home exercises to practice with simple proof automation. *)
Lemma lc_to_lc_c : forall e, lc e -> lc_c e.
(* Take-home exercise. *)
Lemma lc_c_to_lc : forall e, lc_c e -> lc e.
(* Take-home exercise. *)
Lemma typing_c_to_typing : forall E e T,
typing_c E e T -> typing E e T.
(* Take-home exercise: Try to do the same for the following lemma. *)
Lemma value_c_to_value : forall e,
value_c e -> value e.
(* Take-home exercise. *)
Lemma eval_c_to_eval : forall e e',
eval_c e e' -> eval e e'.
Lemma progress : forall e T,
typing nil e T ->
value e \/ exists e', eval e e'.