Set Implicit Arguments.
Require Export Coq.Program.Equality.
(* ---------------------------------------------------------------------------- *)
(* The syntax of untyped lambda-terms. *)
Inductive term :=
| TVar: nat -> term
| TAbs: term -> term
| TApp: term -> term -> term.
(* ---------------------------------------------------------------------------- *)
(* The following definitions allow us to use the [DeBruijn] library. In particular, [traverse_term] defines the binding structure of terms. *)
Instance Var_term : Var term := {
var := TVar (* avoid eta-expansion *)
}.
Fixpoint traverse_term (f : nat -> nat -> term) l t :=
match t with
| TVar x =>
f l x
| TAbs t =>
TAbs (traverse_term f (1 + l) t)
| TApp t1 t2 =>
TApp (traverse_term f l t1) (traverse_term f l t2)
end.
Instance Traverse_term : Traverse term term := {
traverse := traverse_term
}.
Instance TraverseVarInjective_term : @TraverseVarInjective term _ term _.
Instance TraverseFunctorial_term : @TraverseFunctorial term _ term _.
Instance TraverseRelative_term : @TraverseRelative term term _.
Instance TraverseIdentifiesVar_term : @TraverseIdentifiesVar term _ _.
Instance TraverseVarIsIdentity_term : @TraverseVarIsIdentity term _ term _.
(* ---------------------------------------------------------------------------- *)
(* The following lemmas characterize [lift] and [subst]. In principle, the user does not need to explicitly state these lemmas, and that is fortunate. Here, we prove these lemmas only in order to illustrate how the tactics [simpl_lift] and [simpl_subst] can simplify applications of [lift] and [subst]. *)
(* ---------------------------------------------------------------------------- *)
(* Reduction semantics. *)
Inductive red : term -> term -> Prop :=
| RedBeta:
forall t1 t2 t,
subst t2 0 t1 = t ->
red (TApp (TAbs t1) t2) t
| RedContextTAbs:
forall t1 t2,
red t1 t2 ->
red (TAbs t1) (TAbs t2)
| RedContextTAppLeft:
forall t1 t2 t,
red t1 t2 ->
red (TApp t1 t) (TApp t2 t)
| RedContextTAppRight:
forall t1 t2 t,
red t1 t2 ->
red (TApp t t1) (TApp t t2).
(* The reduction judgement is compatible with weakening. *)
(* ---------------------------------------------------------------------------- *)
(* Working with closedness. *)
(* Again, we prove the following lemmas only in order to illustrate the use of the tactic [inversion_closed]. *)

Lemma inversion_closed_TApp_2:
forall t1 t2 k,
closed k (TApp t1 t2) ->
closed k t2.