(*Realizer [e:env; A,M:term] Cases (fix_add_typ e A) of Dcl_ok => Cases (fix_inference M (cons ? (Ax A) e)) of (inl TM) => Cases (not_topsort TM) of (inleft s) => (inr term ? (Lambda_topsort (Abs A M) s)) | _ => (inl ? type_error (Prod A TM)) end | (inr err) => (inr term ? (Under A err)) end | (Dcl_fail err) => (inr term ? err) end. *)
intros.
case (fix_add_typ e A); trivial; intros.
case (fix_inference M (Ax A :: e)); trivial;
[ intros (TM, ppty_M) | intros (err, expl, is_err) ].
case (not_topsort TM); [ intros (s, is_s, tops) | intros ].
right.
exists (Lambda_topsort (Abs A M) s); auto with pts.
constructor.
rewrite <- is_s; trivial.
red in |- *; intros.
apply tops.
Inversion_typ H0.
split with s2; trivial.
left.
exists (Prod A TM).
split; intros.
elimtype (exists s' : sort, typ (Ax A :: e) TM (Srt s')); intros.
inversion_clear w.
elim (pa_infer_rule the_algos) with s x; intros.
apply type_abs with x0; auto with pts.
apply type_prod_sat with s x; auto with pts.
apply (pp_ok p).
apply (pp_ok ppty_M).
generalize t.
elim type_correctness with (1 := pp_ok ppty_M); intros.
split with s; trivial with pts.
elim t0 with s; trivial with pts; intros.
split with x.
constructor; auto with pts.
Inversion_typ H0.
apply le_type_trans with (2 := H3).
apply (pa_le_type_prod the_algos); auto with pts.
apply (pp_least ppty_M) with (1 := H1).
right.
split with (Under A err).
constructor; trivial.
apply Infe_under with M; trivial with pts.
right.
exists err; auto with pts.
inversion_clear d.
apply Infe_subt with A; trivial with pts.
constructor.
Defined.

(* Specifications: *)
Theorem infer_prod :
forall (e : env) (A B : term), wf e -> infer_ppal_type e (Prod A B).