(* ---------------------------------------------------------------------------- *)

(* The syntax of untyped lambda-terms. *)

Inductive term :=
  | TVar: nat -> term
  | TAbs: term -> term
  | TApp: term -> term -> term.(* ---------------------------------------------------------------------------- *)

(* The syntax of untyped lambda-terms. *)

Inductive term :=
  | TVar: nat -> term
  | TAbs: term -> term
  | TApp: term -> term -> term.(* ---------------------------------------------------------------------------- *)

(* The syntax of untyped lambda-terms. *)

Inductive term :=
  | TVar: nat -> term
  | TAbs: term -> term
  | TApp: term -> term -> term.(* ---------------------------------------------------------------------------- *)

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

(* Specifications: *)
Lemma lift_TVar: forall w k x, lift w k (TVar x) = TVar (lift w k x).
Lemma lift_TApp: forall w k t1 t2, lift w k (TApp t1 t2) = TApp (lift w k t1) (lift w k t2).
Lemma lift_TAbs: forall w k t, lift w k (TAbs t) = TAbs (lift w (1 + k) t).
Lemma subst_TVar: forall v k x, subst v k (TVar x) = subst_idx v k x.
Lemma subst_TApp: forall v k t1 t2, subst v k (TApp t1 t2) = TApp (subst v k t1) (subst v k t2).
Lemma subst_TAbs: forall v k t, subst v k (TAbs t) = TAbs (subst (shift 0 v) (1 + k) t).