Section HuetDefinition.
Variable (s t v1 v2: exp X).
Hypothesis (E1: s ▷ v1) (E2: t ▷ v2).
End HuetDefinition.
End Equivalence.
Notation "s ≡ t" := (equiv step s t) (at level 70).
Hint Resolve equiv_neq_var_app equiv_neq_var_lambda equiv_neq_var_const
equiv_neq_const_app equiv_neq_const_lam equiv_neq_lambda_app : core.
Ltac ClearRefl H :=
let T := type of H in
match T with
| ?X ≡ ?X => clear H
| _ => idtac
end.
Ltac Injection H :=
let T := type of H in
let H1 := fresh "H" in
let H2 := fresh "H" in
match T with
| var _ ≡ var _ => eapply equiv_var_eq in H as H1; ClearRefl H1
| const _ ≡ const _ => eapply equiv_const_eq in H as H1; ClearRefl H1
| lambda _ ≡ lambda _ => eapply equiv_lam_elim in H as H1; ClearRefl H1
| app _ _ ≡ app _ _ =>  eapply equiv_app_elim in H as [H1 H2]; [| atom..]; ClearRefl H1; ClearRefl H2
end.
Ltac Discriminate :=
match goal with
| [H: var _ ≡ const _ |- _] => eapply equiv_neq_var_const in H as []
| [H: const _ ≡ var _ |- _] => symmetry in H; eapply equiv_neq_var_const in H as []
| [H: var _ ≡ app _ _ |- _] => solve [eapply equiv_neq_var_app in H as []; atom]
| [H: app _ _ ≡ var _ |- _] => solve [symmetry in H; eapply equiv_neq_var_app in H as []; atom]
| [H: var _ ≡ lambda _ |- _] => eapply equiv_neq_var_lambda in H as []
| [H: lambda _ ≡ var _ |- _] => symmetry in H; eapply equiv_neq_var_lambda in H as []
| [H: const _ ≡ lambda _ |- _] => eapply equiv_neq_const_lam in H as []
| [H: lambda _ ≡ const _ |- _] => symmetry in H; eapply equiv_neq_const_lam in H as []
| [H: const _ ≡ app _ _ |- _] => solve [eapply equiv_neq_const_app in H as []; atom]
| [H: app _ _ ≡ const _ |- _] => solve [symmetry in H; eapply equiv_neq_const_app in H as []; atom]
| [H: lambda _ ≡ app _ _ |- _] => solve [eapply equiv_neq_lambda_app in H as []; atom]
| [H: app _ _ ≡ lambda _ |- _] => solve [symmetry in H; eapply equiv_neq_lambda_app in H as []; atom]
| [H: var _ ≡ var _ |- _] => solve [eapply equiv_var_eq in H as ?; discriminate]
| [H: const _ ≡ const _ |- _] => solve [eapply equiv_const_eq in H as ?; discriminate]
end.

Lemma equiv_head_equal X (s t: exp X):
s ≡ t -> isAtom (head s) -> isAtom (head t) -> head s = head t.