Module SafePolyType.
(* s1 -> .. sn -> x where n <= x *)
Fixpoint is_safe_poly_arr (n: nat) (t: poly_type) :=
match t with
| poly_var x => n <= x
| poly_arr _ t => is_safe_poly_arr n t
| poly_abs _ => False
end.
(* ∀ .. ∀ s1 -> .. sn -> x where x is free *)
Fixpoint is_safe_poly_type (n: nat) (t: poly_type) :=
if t is poly_abs t then is_safe_poly_type (1+n) t else is_safe_poly_arr n t.
(* ∀ .. ∀ s1 -> .. sn -> x where x is free *)
Definition safe_poly_type (n: nat) (ts: list poly_type) (x: nat) :=
many_poly_abs n (many_poly_arr ts (poly_var (n + x))).

Lemma typing_safe_poly_typeE {Gamma P n ss x As y} :
typing Gamma P (many_poly_abs n (many_poly_arr ss (poly_var (n+x)))) ->
typing Gamma (many_argument_app P As) (poly_var y) ->
exists (ts : list poly_type) (Qs : list term),
x = y /\
As = (map argument_poly_type ts) ++ (map argument_term Qs) /\
n = length ts /\
length ss = length Qs.