Module DoNotation.
Notation "'do!' X <- A ; B" :=
(bindGen A (fun X => B))
(at level 200, X ident, A at level 100, B at level 200).
End DoNotation.
(* Sized generator of simple types *)
Fixpoint gen_type_size (n : nat) : G type :=
match n with
| 0 => returnGen N
| S n' =>
do! m <- choose (0, n');
liftGen2 Arrow (gen_type_size (n' - m)) (gen_type_size (n' - (n' - m)))
end.
(* Generator of simple types *)
Definition gen_type : G type := bindGen arbitrary gen_type_size.
(* Returns the list of bindings that have type tau in e *)
Definition vars_with_type (e : env) (tau : type) : list term :=
map (fun p => Id (snd p))
(filter (fun p => proj1_sig (Sumbool.bool_of_sumbool (type_eq_dec tau (fst p))))
(combine e (seq 0 (List.length e)))).
Definition sigT_of_prod {A B : Type} (p : A * B) : {_ : A & B} :=
let (a, b) := p in existT (fun _ : A => B) a b.
Definition lt_pair (c1 c2 : (nat * type)) : Prop :=
lexprod nat (fun _ => type) lt (fun _ => lt_type) (sigT_of_prod c1) (sigT_of_prod c2).

Lemma wf_lt_pair : well_founded lt_pair.