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 is_safe_poly_typeE {i t} : is_safe_poly_type i t ->
exists (n : nat) (ts : list poly_type) (x : nat),
t = many_poly_abs n (many_poly_arr ts (poly_var (n + (i + x)))).