(* Autor(s): Andrej Dudenhefner (1) Yannick Forster (1) Affiliation(s): (1) Saarland University, Saarbrücken, Germany *)
From Undecidability.SystemF.Util Require Import Facts poly_type_facts term_facts.
Arguments funcomp {X Y Z} _ _ / _.
(* Church-style System F Type Assignment Predicate *)
Inductive typing : environment -> term -> poly_type -> Prop :=
| typing_var {Gamma x t} :
nth_error Gamma x = Some t -> typing Gamma (var x) t
| typing_app {Gamma P Q s t} :
typing Gamma P (poly_arr s t) -> typing Gamma Q s -> typing Gamma (app P Q) t
| typing_abs {Gamma P s t} :
typing (s :: Gamma) P t -> typing Gamma (abs s P) (poly_arr s t)
| typing_ty_app {Gamma P s t} :
typing Gamma P (poly_abs s) -> typing Gamma (ty_app P t) (subst_poly_type (scons t poly_var) s)
| typing_ty_abs {Gamma P s} :
typing (map (ren_poly_type S) Gamma) P s -> typing Gamma (ty_abs P) (poly_abs s).

(* case analysis on the typing predicate wrt. term *)
Lemma typingE {Gamma P t} : typing Gamma P t ->
match P with
| var x => nth_error Gamma x = Some t
| app P Q => exists s, typing Gamma P (poly_arr s t) /\ typing Gamma Q s
| abs s P => exists t', t = poly_arr s t' /\ typing (s :: Gamma) P t'
| ty_app P t' => exists s, t = (subst_poly_type (t' .: poly_var) s) /\ typing Gamma P (poly_abs s)
| ty_abs P => exists s, t = (poly_abs s) /\ typing (map (ren_poly_type S) Gamma) P s
end.