(* Application to values & terms. *)

Inductive my_term :=
  | MyTValue: my_value -> my_term
  | MyTApp: my_term -> my_term -> my_term

with my_value :=
  | MyVVar: nat -> my_value
  | MyVAbs: my_term -> my_value.(* Application to values & terms. *)

Inductive my_term :=
  | MyTValue: my_value -> my_term
  | MyTApp: my_term -> my_term -> my_term

with my_value :=
  | MyVVar: nat -> my_value
  | MyVAbs: my_term -> my_value.(* Application to values & terms. *)

Inductive my_term :=
  | MyTValue: my_value -> my_term
  | MyTApp: my_term -> my_term -> my_term

with my_value :=
  | MyVVar: nat -> my_value
  | MyVAbs: my_term -> my_value.(* Application to values & terms. *)

Inductive my_term :=
  | MyTValue: my_value -> my_term
  | MyTApp: my_term -> my_term -> my_term

with my_value :=
  | MyVVar: nat -> my_value
  | MyVAbs: my_term -> my_value.(* Application to values & terms. *)

Inductive my_term :=
  | MyTValue: my_value -> my_term
  | MyTApp: my_term -> my_term -> my_term

with my_value :=
  | MyVVar: nat -> my_value
  | MyVAbs: my_term -> my_value.(* Application to values & terms. *)

Inductive my_term :=
  | MyTValue: my_value -> my_term
  | MyTApp: my_term -> my_term -> my_term

with my_value :=
  | MyVVar: nat -> my_value
  | MyVAbs: my_term -> my_value.Instance Var_my_value : Var my_value := {
  var := MyVVar
}.Fixpoint traverse_my_term (f : nat -> nat -> my_value) l t :=
  match t with
  | MyTValue v =>
      MyTValue (traverse_my_value f l v)
  | MyTApp t1 t2 =>
      MyTApp (traverse_my_term f l t1) (traverse_my_term f l t2)
  end

with traverse_my_value f l v :=
  match v with
  | MyVVar x =>
      f l x
  | MyVAbs t =>
      MyVAbs (traverse_my_term f (1 + l) t)
  end.Instance Traverse_my_value_my_value : Traverse my_value my_value := {
  traverse := traverse_my_value
}.Instance Traverse_my_value_my_term : Traverse my_value my_term := {
  traverse := traverse_my_term
}.

Lemma traverse_my_value_injective: forall f, (forall x1 x2 l, f l x1 = f l x2 -> x1 = x2) -> forall (t1 t2 : my_value) l, traverse_var f l t1 = traverse_var f l t2 -> t1 = t2 with traverse_my_term_injective: forall f, (forall x1 x2 l, f l x1 = f l x2 -> x1 = x2) -> forall (t1 t2 : my_term) l, traverse_var f l t1 = traverse_var f l t2 -> t1 = t2.