(* 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'.

(* copying, permuting, and adding new assumptions to the environment preserves derivations *)
Lemma typing_ren_term {ξ Gamma Delta P t} :
(forall n s, nth_error Gamma n = Some s -> nth_error Delta (ξ n) = Some s) ->
typing Gamma P t ->
typing Delta (ren_term id ξ P) t.