Ltac destruct_match H :=
match type of H with
| context [ match ?x with _ => _  end] => destruct x eqn:?
end.

(* Specifications: *)
Lemma exprD'_App_R_typ (e1 e2 : expr typ func) tus tvs ty1 ty2 v: exprD' tus tvs ty2 (App e1 e2) = Some v -> typeof_expr tus tvs e2 = Some ty1 -> (exists v1 , exprD' tus tvs (tyArr ty1 ty2) e1 = Some v1) /\ (exists v2, exprD' tus tvs ty1 e2 = Some v2).
Lemma exprD'_App_L_typ (e1 e2 : expr typ func) tus tvs ty1 ty2 v: exprD' tus tvs ty2 (App e1 e2) = Some v -> typeof_expr tus tvs e1 = Some (tyArr ty1 ty2) -> (exists v1 , exprD' tus tvs (tyArr ty1 ty2) e1 = Some v1) /\ (exists v2, exprD' tus tvs ty1 e2 = Some v2).
Lemma exprD_typeof_Some : forall tus tvs t (e : expr typ func) val, exprD' tus tvs t e = Some val -> typeof_expr tus tvs e = Some t.
Lemma typeof_app : forall (e1 e2 : expr typ func) t tvs tus, typeof_expr tus tvs (App e1 e2) = Some t -> exists t2, typeof_expr tus tvs e1 = Some (tyArr t2 t) /\ typeof_expr tus tvs e2 = Some (t2).
Lemma exprD_ex_typs : forall tus tvs t (e1 e2 : expr typ func) v, exprD' tus tvs t (App e1 e2) = Some v -> exists t2, typeof_expr tus tvs e1 = Some (tyArr t2 t) /\ typeof_expr tus tvs e2 = Some (t2).
Lemma exprD'_one_type : forall tus tvs t1 t2 (e : expr typ func) v1 v2, exprD' tus tvs t1 e = Some v1 -> exprD' tus tvs t2 e = Some v2 -> t1 = t2.