(* 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).
Fact typing_many_argument_subterm {Gamma P As t} : typing Gamma (many_argument_app P As) t ->
exists t', typing Gamma P t'.

Lemma typing_many_ty_appI {Gamma P n t ts} :
length ts = n ->
typing Gamma P (many_poly_abs n t) ->
typing Gamma (many_ty_app P ts) (subst_poly_type (fold_right scons poly_var (rev ts)) t).