(*************************************************************************)
(** * Typing relation *)
(*************************************************************************)
(** The definition of the typing relation is straightforward.  In order to ensure that the relation holds for only well-formed environments, we check in the [typing_var] case that the environment is [uniq].  The structure of typing derivations implicitly ensures that the relation holds only for locally closed expressions.  Finally, note the use of cofinite quantification in the [typing_abs] case. *)
Inductive typing_c : env -> exp -> typ -> Prop :=
| typing_var_c : forall E (x : atom) T,
uniq E ->
binds x T E ->
typing_c E (fvar x) T
| typing_abs_c : forall (L : atoms) E e T1 T2,
(forall (x:atom), x `notin` L ->
typing_c ((x ~ T1) ++ E) (open e x) T2) ->
typing_c E (abs T1 e) (typ_arrow T1 T2)
| typing_app_c : forall E e1 e2 T1 T2,
typing_c E e1 (typ_arrow T1 T2) ->
typing_c E e2 T1 ->
typing_c E (app e1 e2) T2.
(** We add the constructors of the typing relation as hints to be used by the [auto] and [eauto] tactics. *)
Hint Constructors typing_c.
(*************************************************************************)
(** * Weakening *)
(*************************************************************************)
(** Weakening states that if an expression is typeable in some environment, then it is typeable in any well-formed extension of that environment.  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]. *)

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