(*************************************************************************)
(** * Typing relation and cofinite quantification *)
(*************************************************************************)
(** The typing relation in the STLC definition states the typing rule for abstractions in a particular way.  << typing_abs : forall (L : atoms) (G : ctx) (T1 : typ) (e : exp) (T2 : typ), (forall x : atom, x `notin` L -> typing ([(x, T1)] ++ G) (open e (var_f x)) T2) -> typing G (abs e) (typ_arrow T1 T2) >>  To show that abstractions are well-typed, we must show that the body of the abstraction is well-typed for any choice of variable, except those from some unspecified set `L`.  This type of rule differs from the quantification in the [lc_abs] rule (which does not restrict the variables at all) or the [lc_abs_exists] version (which only applies for one particular variable. We call this version "co-finite" quantification.  To see why this version is necessary, we will start with a more traditional version of the rules that only uses a single variable in the abs rule and then see what goes wrong. (We say that the [typing_e] judgement below uses "exists-fresh" quantification in the abs rule.)  *)
Inductive typing_e : ctx -> exp -> typ -> Prop :=
| typing_e_var : forall E (x : atom) T,
uniq E ->
binds x T E ->
typing_e E (var_f x) T
| typing_e_abs : forall x E e T1 T2,
x `notin` dom E \u fv_exp e ->
typing_e ([(x, T1)] ++ E) (e ^ x) T2 ->
typing_e E (abs e) (typ_arrow T1 T2)
| typing_e_app : forall E e1 e2 T1 T2,
typing_e E e1 (typ_arrow T1 T2) ->
typing_e E e2 T1 ->
typing_e E (app e1 e2) T2.
Hint Constructors typing_e.
(*************************************************************************)
(** ** Weakening  *)
(*************************************************************************)
(** Weakening states that if an expression is typeable in some context, then it is typeable in any well-formed extension of that context.  This property is needed to prove the substitution lemma.  As stated below, this lemma is not directly proveable.  The natural way to try proving this lemma proceeds by induction on the typing derivation for [e]. *)

(* Specifications: *)
Lemma typing_weakening_0 : forall E F e T,
typing_e E e T ->
uniq (F ++ E) ->
typing_e (F ++ E) e T.