Reasoning Details

 < Module stlc:host.
 < Theorem lookup_ty_is :
     forall Ctx X Ty,
       is_list (is_pair is_string is_ty) Ctx -> lookup Ctx X Ty -> is_ty Ty.

============================
 forall Ctx X Ty,
   is_list (is_pair is_string is_ty) Ctx -> lookup Ctx X Ty -> is_ty Ty
 < induction on 2.

IH : forall Ctx X Ty,
       is_list (is_pair is_string is_ty) Ctx -> lookup Ctx X Ty * -> is_ty Ty
============================
 forall Ctx X Ty,
   is_list (is_pair is_string is_ty) Ctx -> lookup Ctx X Ty @ -> is_ty Ty
 < intros Is L.

Variables: Ctx X Ty
IH : forall Ctx X Ty,
       is_list (is_pair is_string is_ty) Ctx -> lookup Ctx X Ty * -> is_ty Ty
Is : is_list (is_pair is_string is_ty) Ctx
L : lookup Ctx X Ty @
============================
 is_ty Ty
 < L: case L.

Subgoal 1:

Variables: X Ty Rest
IH : forall Ctx X Ty,
       is_list (is_pair is_string is_ty) Ctx -> lookup Ctx X Ty * -> is_ty Ty
Is : is_list (is_pair is_string is_ty) ((X, Ty)::Rest)
============================
 is_ty Ty
 < Is: case Is.

Subgoal 1:

Variables: X Ty Rest
IH : forall Ctx X Ty,
       is_list (is_pair is_string is_ty) Ctx -> lookup Ctx X Ty * -> is_ty Ty
Is : is_pair is_string is_ty (X, Ty)
Is1 : is_list (is_pair is_string is_ty) Rest
============================
 is_ty Ty
 < case Is.

Subgoal 1:

Variables: X Ty Rest
IH : forall Ctx X Ty,
       is_list (is_pair is_string is_ty) Ctx -> lookup Ctx X Ty * -> is_ty Ty
Is1 : is_list (is_pair is_string is_ty) Rest
H1 : is_string X
H2 : is_ty Ty
============================
 is_ty Ty
 < search.

Subgoal 2:

Variables: X Ty Rest V K
IH : forall Ctx X Ty,
       is_list (is_pair is_string is_ty) Ctx -> lookup Ctx X Ty * -> is_ty Ty
Is : is_list (is_pair is_string is_ty) ((K, V)::Rest)
L : K = X -> false
L1 : lookup Rest X Ty *
============================
 is_ty Ty
 < Is: case Is.

Subgoal 2:

Variables: X Ty Rest V K
IH : forall Ctx X Ty,
       is_list (is_pair is_string is_ty) Ctx -> lookup Ctx X Ty * -> is_ty Ty
L : K = X -> false
L1 : lookup Rest X Ty *
Is : is_pair is_string is_ty (K, V)
Is1 : is_list (is_pair is_string is_ty) Rest
============================
 is_ty Ty
 < apply IH to _ L1.

Subgoal 2:

Variables: X Ty Rest V K
IH : forall Ctx X Ty,
       is_list (is_pair is_string is_ty) Ctx -> lookup Ctx X Ty * -> is_ty Ty
L : K = X -> false
L1 : lookup Rest X Ty *
Is : is_pair is_string is_ty (K, V)
Is1 : is_list (is_pair is_string is_ty) Rest
H1 : is_ty Ty
============================
 is_ty Ty
 < search.

Proof completed.
 < Projection_Constraint proj_ty_is :
   forall Ty Ty',
   Proj : |{ty}- Ty ~~> Ty' ->
   IsTy : is_ty Ty ->
   is_ty Ty'.

Proof completed.
 < Extensible_Theorem
      type_is : forall Ctx T Ty,
         IsCtx : is_list (is_pair is_string is_ty) Ctx ->
         IsT : is_tm T ->
         Ty : typeOf Ctx T Ty ->
         is_ty Ty
      on Ty.

Subgoal 1:

Variables: Ctx Ty X
IH : forall Ctx T Ty,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T Ty * -> is_ty Ty
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (var X)
Ty : typeOf Ctx (var X) Ty @
Ty1 : lookup Ctx X Ty
============================
 is_ty Ty
 < apply lookup_ty_is to _ Ty1.

Subgoal 1:

Variables: Ctx Ty X
IH : forall Ctx T Ty,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T Ty * -> is_ty Ty
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (var X)
Ty : typeOf Ctx (var X) Ty @
Ty1 : lookup Ctx X Ty
H1 : is_ty Ty
============================
 is_ty Ty
 < search.

Subgoal 2:

Variables: Ctx Ty2 Ty1 Body X
IH : forall Ctx T Ty,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T Ty * -> is_ty Ty
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (abs X Ty1 Body)
Ty : typeOf Ctx (abs X Ty1 Body) (arrowTy Ty1 Ty2) @
Ty1 : typeOf ((X, Ty1)::Ctx) Body Ty2 *
============================
 is_ty (arrowTy Ty1 Ty2)
 < Is: case IsT.

Subgoal 2:

Variables: Ctx Ty2 Ty1 Body X
IH : forall Ctx T Ty,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T Ty * -> is_ty Ty
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (abs X Ty1 Body) (arrowTy Ty1 Ty2) @
Ty1 : typeOf ((X, Ty1)::Ctx) Body Ty2 *
Is : is_string X
Is1 : is_ty Ty1
Is2 : is_tm Body
============================
 is_ty (arrowTy Ty1 Ty2)
 < apply IH to _ _ Ty1.

Subgoal 2:

Variables: Ctx Ty2 Ty1 Body X
IH : forall Ctx T Ty,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T Ty * -> is_ty Ty
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (abs X Ty1 Body) (arrowTy Ty1 Ty2) @
Ty1 : typeOf ((X, Ty1)::Ctx) Body Ty2 *
Is : is_string X
Is1 : is_ty Ty1
Is2 : is_tm Body
H1 : is_ty Ty2
============================
 is_ty (arrowTy Ty1 Ty2)
 < search.

Subgoal 3:

Variables: Ctx Ty Ty1 T2 T1
IH : forall Ctx T Ty,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T Ty * -> is_ty Ty
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (app T1 T2)
Ty : typeOf Ctx (app T1 T2) Ty @
Ty1 : typeOf Ctx T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf Ctx T2 Ty1 *
============================
 is_ty Ty
 < Is: case IsT.

Subgoal 3:

Variables: Ctx Ty Ty1 T2 T1
IH : forall Ctx T Ty,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T Ty * -> is_ty Ty
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (app T1 T2) Ty @
Ty1 : typeOf Ctx T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf Ctx T2 Ty1 *
Is : is_tm T1
Is1 : is_tm T2
============================
 is_ty Ty
 < IsTy: apply IH to _ _ Ty1.

Subgoal 3:

Variables: Ctx Ty Ty1 T2 T1
IH : forall Ctx T Ty,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T Ty * -> is_ty Ty
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (app T1 T2) Ty @
Ty1 : typeOf Ctx T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf Ctx T2 Ty1 *
Is : is_tm T1
Is1 : is_tm T2
IsTy : is_ty (arrowTy Ty1 Ty)
============================
 is_ty Ty
 < case IsTy.

Subgoal 3:

Variables: Ctx Ty Ty1 T2 T1
IH : forall Ctx T Ty,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T Ty * -> is_ty Ty
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (app T1 T2) Ty @
Ty1 : typeOf Ctx T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf Ctx T2 Ty1 *
Is : is_tm T1
Is1 : is_tm T2
H1 : is_ty Ty1
H2 : is_ty Ty
============================
 is_ty Ty
 < search.

Subgoal 4:

Variables: Ctx I
IH : forall Ctx T Ty,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T Ty * -> is_ty Ty
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (num I)
Ty : typeOf Ctx (num I) intTy @
============================
 is_ty intTy
 < search.

Subgoal 5:

Variables: Ctx T2 T1
IH : forall Ctx T Ty,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T Ty * -> is_ty Ty
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (plus T1 T2)
Ty : typeOf Ctx (plus T1 T2) intTy @
Ty1 : typeOf Ctx T1 intTy *
Ty2 : typeOf Ctx T2 intTy *
============================
 is_ty intTy
 < search.

Proof completed.
 < Projection_Constraint proj_is :
   forall Ctx T T',
   Proj : Ctx |{tm}- T ~~> T' ->
   IsCtx : is_list (is_pair is_string is_ty) Ctx ->
   IsT : is_tm T ->
   is_tm T'.

Proof completed.
 < Extensible_Theorem
      type_unique : forall Ctx T TyA TyB,
         IsCtx : is_list (is_pair is_string is_ty) Ctx ->
         IsT : is_tm T ->
         TyA : typeOf Ctx T TyA ->
         TyB : typeOf Ctx T TyB ->
         TyA = TyB
      on TyA.

Subgoal 1:

Variables: Ctx TyA TyB X
IH : forall Ctx T TyA TyB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T TyA * ->
       typeOf Ctx T TyB -> TyA = TyB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (var X)
TyA : typeOf Ctx (var X) TyA @
TyB : typeOf Ctx (var X) TyB
TyA1 : lookup Ctx X TyA
============================
 TyA = TyB
 < TyB: case TyB.

Subgoal 1:

Variables: Ctx TyA TyB X
IH : forall Ctx T TyA TyB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T TyA * ->
       typeOf Ctx T TyB -> TyA = TyB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (var X)
TyA : typeOf Ctx (var X) TyA @
TyA1 : lookup Ctx X TyA
TyB : lookup Ctx X TyB
============================
 TyA = TyB
 < apply lookup_unique to TyA1 TyB.

Subgoal 1:

Variables: Ctx TyB X
IH : forall Ctx T TyA TyB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T TyA * ->
       typeOf Ctx T TyB -> TyA = TyB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (var X)
TyA : typeOf Ctx (var X) TyB @
TyA1 : lookup Ctx X TyB
TyB : lookup Ctx X TyB
============================
 TyB = TyB
 < search.

Subgoal 2:

Variables: Ctx TyB Ty2 Ty1 Body X
IH : forall Ctx T TyA TyB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T TyA * ->
       typeOf Ctx T TyB -> TyA = TyB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (abs X Ty1 Body)
TyA : typeOf Ctx (abs X Ty1 Body) (arrowTy Ty1 Ty2) @
TyB : typeOf Ctx (abs X Ty1 Body) TyB
TyA1 : typeOf ((X, Ty1)::Ctx) Body Ty2 *
============================
 arrowTy Ty1 Ty2 = TyB
 < case IsT.

Subgoal 2:

Variables: Ctx TyB Ty2 Ty1 Body X
IH : forall Ctx T TyA TyB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T TyA * ->
       typeOf Ctx T TyB -> TyA = TyB
IsCtx : is_list (is_pair is_string is_ty) Ctx
TyA : typeOf Ctx (abs X Ty1 Body) (arrowTy Ty1 Ty2) @
TyB : typeOf Ctx (abs X Ty1 Body) TyB
TyA1 : typeOf ((X, Ty1)::Ctx) Body Ty2 *
H1 : is_string X
H2 : is_ty Ty1
H3 : is_tm Body
============================
 arrowTy Ty1 Ty2 = TyB
 < TyB: case TyB.

Subgoal 2:

Variables: Ctx Ty2 Ty1 Body X Ty4
IH : forall Ctx T TyA TyB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T TyA * ->
       typeOf Ctx T TyB -> TyA = TyB
IsCtx : is_list (is_pair is_string is_ty) Ctx
TyA : typeOf Ctx (abs X Ty1 Body) (arrowTy Ty1 Ty2) @
TyA1 : typeOf ((X, Ty1)::Ctx) Body Ty2 *
H1 : is_string X
H2 : is_ty Ty1
H3 : is_tm Body
TyB : typeOf ((X, Ty1)::Ctx) Body Ty4
============================
 arrowTy Ty1 Ty2 = arrowTy Ty1 Ty4
 < apply IH to _ _ TyA1 TyB.

Subgoal 2:

Variables: Ctx Ty1 Body X Ty4
IH : forall Ctx T TyA TyB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T TyA * ->
       typeOf Ctx T TyB -> TyA = TyB
IsCtx : is_list (is_pair is_string is_ty) Ctx
TyA : typeOf Ctx (abs X Ty1 Body) (arrowTy Ty1 Ty4) @
TyA1 : typeOf ((X, Ty1)::Ctx) Body Ty4 *
H1 : is_string X
H2 : is_ty Ty1
H3 : is_tm Body
TyB : typeOf ((X, Ty1)::Ctx) Body Ty4
============================
 arrowTy Ty1 Ty4 = arrowTy Ty1 Ty4
 < search.

Subgoal 3:

Variables: Ctx TyA TyB Ty1 T2 T1
IH : forall Ctx T TyA TyB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T TyA * ->
       typeOf Ctx T TyB -> TyA = TyB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (app T1 T2)
TyA : typeOf Ctx (app T1 T2) TyA @
TyB : typeOf Ctx (app T1 T2) TyB
TyA1 : typeOf Ctx T1 (arrowTy Ty1 TyA) *
TyA2 : typeOf Ctx T2 Ty1 *
============================
 TyA = TyB
 < case IsT.

Subgoal 3:

Variables: Ctx TyA TyB Ty1 T2 T1
IH : forall Ctx T TyA TyB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T TyA * ->
       typeOf Ctx T TyB -> TyA = TyB
IsCtx : is_list (is_pair is_string is_ty) Ctx
TyA : typeOf Ctx (app T1 T2) TyA @
TyB : typeOf Ctx (app T1 T2) TyB
TyA1 : typeOf Ctx T1 (arrowTy Ty1 TyA) *
TyA2 : typeOf Ctx T2 Ty1 *
H1 : is_tm T1
H2 : is_tm T2
============================
 TyA = TyB
 < TyB: case TyB.

Subgoal 3:

Variables: Ctx TyA TyB Ty1 T2 T1 Ty2
IH : forall Ctx T TyA TyB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T TyA * ->
       typeOf Ctx T TyB -> TyA = TyB
IsCtx : is_list (is_pair is_string is_ty) Ctx
TyA : typeOf Ctx (app T1 T2) TyA @
TyA1 : typeOf Ctx T1 (arrowTy Ty1 TyA) *
TyA2 : typeOf Ctx T2 Ty1 *
H1 : is_tm T1
H2 : is_tm T2
TyB : typeOf Ctx T1 (arrowTy Ty2 TyB)
TyB1 : typeOf Ctx T2 Ty2
============================
 TyA = TyB
 < apply IH to _ _ TyA1 TyB.

Subgoal 3:

Variables: Ctx TyB T2 T1 Ty2
IH : forall Ctx T TyA TyB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T TyA * ->
       typeOf Ctx T TyB -> TyA = TyB
IsCtx : is_list (is_pair is_string is_ty) Ctx
TyA : typeOf Ctx (app T1 T2) TyB @
TyA1 : typeOf Ctx T1 (arrowTy Ty2 TyB) *
TyA2 : typeOf Ctx T2 Ty2 *
H1 : is_tm T1
H2 : is_tm T2
TyB : typeOf Ctx T1 (arrowTy Ty2 TyB)
TyB1 : typeOf Ctx T2 Ty2
============================
 TyB = TyB
 < apply IH to _ _ TyA2 TyB1.

Subgoal 3:

Variables: Ctx TyB T2 T1 Ty2
IH : forall Ctx T TyA TyB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T TyA * ->
       typeOf Ctx T TyB -> TyA = TyB
IsCtx : is_list (is_pair is_string is_ty) Ctx
TyA : typeOf Ctx (app T1 T2) TyB @
TyA1 : typeOf Ctx T1 (arrowTy Ty2 TyB) *
TyA2 : typeOf Ctx T2 Ty2 *
H1 : is_tm T1
H2 : is_tm T2
TyB : typeOf Ctx T1 (arrowTy Ty2 TyB)
TyB1 : typeOf Ctx T2 Ty2
============================
 TyB = TyB
 < search.

Subgoal 4:

Variables: Ctx TyB I
IH : forall Ctx T TyA TyB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T TyA * ->
       typeOf Ctx T TyB -> TyA = TyB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (num I)
TyA : typeOf Ctx (num I) intTy @
TyB : typeOf Ctx (num I) TyB
============================
 intTy = TyB
 < case TyB.

Subgoal 4:

Variables: Ctx I
IH : forall Ctx T TyA TyB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T TyA * ->
       typeOf Ctx T TyB -> TyA = TyB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (num I)
TyA : typeOf Ctx (num I) intTy @
============================
 intTy = intTy
 < search.

Subgoal 5:

Variables: Ctx TyB T2 T1
IH : forall Ctx T TyA TyB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T TyA * ->
       typeOf Ctx T TyB -> TyA = TyB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (plus T1 T2)
TyA : typeOf Ctx (plus T1 T2) intTy @
TyB : typeOf Ctx (plus T1 T2) TyB
TyA1 : typeOf Ctx T1 intTy *
TyA2 : typeOf Ctx T2 intTy *
============================
 intTy = TyB
 < case TyB.

Subgoal 5:

Variables: Ctx T2 T1
IH : forall Ctx T TyA TyB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> typeOf Ctx T TyA * ->
       typeOf Ctx T TyB -> TyA = TyB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (plus T1 T2)
TyA : typeOf Ctx (plus T1 T2) intTy @
TyA1 : typeOf Ctx T1 intTy *
TyA2 : typeOf Ctx T2 intTy *
H1 : typeOf Ctx T1 intTy
H2 : typeOf Ctx T2 intTy
============================
 intTy = intTy
 < search.

Proof completed.
 < Projection_Constraint proj_ty_unique :
   forall Ty TyA TyB,
   |{ty}- Ty ~~> TyA -> |{ty}- Ty ~~> TyB -> is_ty Ty -> TyA = TyB.

Proof completed.
 < Projection_Constraint proj_tm_unique :
   forall Ctx T TA TB,
   Ctx |{tm}- T ~~> TA -> Ctx |{tm}- T ~~> TB -> is_tm T -> is_list (is_pair is_string is_ty) Ctx ->
   TA = TB.

Proof completed.
 < Extensible_Theorem
      subst_is : forall X R T S,
         IsT : is_tm T ->
         IsX : is_string X ->
         IsR : is_tm R ->
         S : subst X R T S ->
         is_tm S
      on S.

Subgoal 1:

Variables: X R Y
IH : forall X R T S,
       is_tm T -> is_string X -> is_tm R -> subst X R T S * -> is_tm S
IsT : is_tm (var Y)
IsX : is_string X
IsR : is_tm R
S : subst X R (var Y) (var Y) @
S1 : X = Y -> false
============================
 is_tm (var Y)
 < search.

Subgoal 2:

Variables: X S
IH : forall X R T S,
       is_tm T -> is_string X -> is_tm R -> subst X R T S * -> is_tm S
IsT : is_tm (var X)
IsX : is_string X
IsR : is_tm S
S : subst X S (var X) S @
============================
 is_tm S
 < search.

Subgoal 3:

Variables: X R S1 Ty Y B
IH : forall X R T S,
       is_tm T -> is_string X -> is_tm R -> subst X R T S * -> is_tm S
IsT : is_tm (abs Y Ty B)
IsX : is_string X
IsR : is_tm R
S : subst X R (abs Y Ty B) (abs Y Ty S1) @
S1 : X = Y -> false
S2 : subst X R B S1 *
============================
 is_tm (abs Y Ty S1)
 < Is: case IsT.

Subgoal 3:

Variables: X R S1 Ty Y B
IH : forall X R T S,
       is_tm T -> is_string X -> is_tm R -> subst X R T S * -> is_tm S
IsX : is_string X
IsR : is_tm R
S : subst X R (abs Y Ty B) (abs Y Ty S1) @
S1 : X = Y -> false
S2 : subst X R B S1 *
Is : is_string Y
Is1 : is_ty Ty
Is2 : is_tm B
============================
 is_tm (abs Y Ty S1)
 < apply IH to _ _ _ S2.

Subgoal 3:

Variables: X R S1 Ty Y B
IH : forall X R T S,
       is_tm T -> is_string X -> is_tm R -> subst X R T S * -> is_tm S
IsX : is_string X
IsR : is_tm R
S : subst X R (abs Y Ty B) (abs Y Ty S1) @
S1 : X = Y -> false
S2 : subst X R B S1 *
Is : is_string Y
Is1 : is_ty Ty
Is2 : is_tm B
H1 : is_tm S1
============================
 is_tm (abs Y Ty S1)
 < search.

Subgoal 4:

Variables: X R B Ty
IH : forall X R T S,
       is_tm T -> is_string X -> is_tm R -> subst X R T S * -> is_tm S
IsT : is_tm (abs X Ty B)
IsX : is_string X
IsR : is_tm R
S : subst X R (abs X Ty B) (abs X Ty B) @
============================
 is_tm (abs X Ty B)
 < search.

Subgoal 5:

Variables: X R S2 S1 T2 T1
IH : forall X R T S,
       is_tm T -> is_string X -> is_tm R -> subst X R T S * -> is_tm S
IsT : is_tm (app T1 T2)
IsX : is_string X
IsR : is_tm R
S : subst X R (app T1 T2) (app S1 S2) @
S1 : subst X R T1 S1 *
S2 : subst X R T2 S2 *
============================
 is_tm (app S1 S2)
 < Is: case IsT.

Subgoal 5:

Variables: X R S2 S1 T2 T1
IH : forall X R T S,
       is_tm T -> is_string X -> is_tm R -> subst X R T S * -> is_tm S
IsX : is_string X
IsR : is_tm R
S : subst X R (app T1 T2) (app S1 S2) @
S1 : subst X R T1 S1 *
S2 : subst X R T2 S2 *
Is : is_tm T1
Is1 : is_tm T2
============================
 is_tm (app S1 S2)
 < apply IH to _ _ _ S1.

Subgoal 5:

Variables: X R S2 S1 T2 T1
IH : forall X R T S,
       is_tm T -> is_string X -> is_tm R -> subst X R T S * -> is_tm S
IsX : is_string X
IsR : is_tm R
S : subst X R (app T1 T2) (app S1 S2) @
S1 : subst X R T1 S1 *
S2 : subst X R T2 S2 *
Is : is_tm T1
Is1 : is_tm T2
H1 : is_tm S1
============================
 is_tm (app S1 S2)
 < apply IH to _ _ _ S2.

Subgoal 5:

Variables: X R S2 S1 T2 T1
IH : forall X R T S,
       is_tm T -> is_string X -> is_tm R -> subst X R T S * -> is_tm S
IsX : is_string X
IsR : is_tm R
S : subst X R (app T1 T2) (app S1 S2) @
S1 : subst X R T1 S1 *
S2 : subst X R T2 S2 *
Is : is_tm T1
Is1 : is_tm T2
H1 : is_tm S1
H2 : is_tm S2
============================
 is_tm (app S1 S2)
 < search.

Subgoal 6:

Variables: X R I
IH : forall X R T S,
       is_tm T -> is_string X -> is_tm R -> subst X R T S * -> is_tm S
IsT : is_tm (num I)
IsX : is_string X
IsR : is_tm R
S : subst X R (num I) (num I) @
============================
 is_tm (num I)
 < search.

Subgoal 7:

Variables: X R S2 S1 T2 T1
IH : forall X R T S,
       is_tm T -> is_string X -> is_tm R -> subst X R T S * -> is_tm S
IsT : is_tm (plus T1 T2)
IsX : is_string X
IsR : is_tm R
S : subst X R (plus T1 T2) (plus S1 S2) @
S1 : subst X R T1 S1 *
S2 : subst X R T2 S2 *
============================
 is_tm (plus S1 S2)
 < Is: case IsT.

Subgoal 7:

Variables: X R S2 S1 T2 T1
IH : forall X R T S,
       is_tm T -> is_string X -> is_tm R -> subst X R T S * -> is_tm S
IsX : is_string X
IsR : is_tm R
S : subst X R (plus T1 T2) (plus S1 S2) @
S1 : subst X R T1 S1 *
S2 : subst X R T2 S2 *
Is : is_tm T1
Is1 : is_tm T2
============================
 is_tm (plus S1 S2)
 < apply IH to _ _ _ S1.

Subgoal 7:

Variables: X R S2 S1 T2 T1
IH : forall X R T S,
       is_tm T -> is_string X -> is_tm R -> subst X R T S * -> is_tm S
IsX : is_string X
IsR : is_tm R
S : subst X R (plus T1 T2) (plus S1 S2) @
S1 : subst X R T1 S1 *
S2 : subst X R T2 S2 *
Is : is_tm T1
Is1 : is_tm T2
H1 : is_tm S1
============================
 is_tm (plus S1 S2)
 < apply IH to _ _ _ S2.

Subgoal 7:

Variables: X R S2 S1 T2 T1
IH : forall X R T S,
       is_tm T -> is_string X -> is_tm R -> subst X R T S * -> is_tm S
IsX : is_string X
IsR : is_tm R
S : subst X R (plus T1 T2) (plus S1 S2) @
S1 : subst X R T1 S1 *
S2 : subst X R T2 S2 *
Is : is_tm T1
Is1 : is_tm T2
H1 : is_tm S1
H2 : is_tm S2
============================
 is_tm (plus S1 S2)
 < search.

Proof completed.
 < Extensible_Theorem
      eval_is : forall T T',
         IsT : is_tm T ->
         Ev : eval T T' ->
         is_tm T'
      on Ev.

Subgoal 1:

Variables: T2 T11 T1
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
IsT : is_tm (app T1 T2)
Ev : eval (app T1 T2) (app T11 T2) @
Ev1 : eval T1 T11 *
============================
 is_tm (app T11 T2)
 < Is: case IsT.

Subgoal 1:

Variables: T2 T11 T1
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
Ev : eval (app T1 T2) (app T11 T2) @
Ev1 : eval T1 T11 *
Is : is_tm T1
Is1 : is_tm T2
============================
 is_tm (app T11 T2)
 < apply IH to _ Ev1.

Subgoal 1:

Variables: T2 T11 T1
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
Ev : eval (app T1 T2) (app T11 T2) @
Ev1 : eval T1 T11 *
Is : is_tm T1
Is1 : is_tm T2
H1 : is_tm T11
============================
 is_tm (app T11 T2)
 < search.

Subgoal 2:

Variables: T21 T1 T2
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
IsT : is_tm (app T1 T2)
Ev : eval (app T1 T2) (app T1 T21) @
Ev1 : value T1
Ev2 : eval T2 T21 *
============================
 is_tm (app T1 T21)
 < Is: case IsT.

Subgoal 2:

Variables: T21 T1 T2
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
Ev : eval (app T1 T2) (app T1 T21) @
Ev1 : value T1
Ev2 : eval T2 T21 *
Is : is_tm T1
Is1 : is_tm T2
============================
 is_tm (app T1 T21)
 < apply IH to _ Ev2.

Subgoal 2:

Variables: T21 T1 T2
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
Ev : eval (app T1 T2) (app T1 T21) @
Ev1 : value T1
Ev2 : eval T2 T21 *
Is : is_tm T1
Is1 : is_tm T2
H1 : is_tm T21
============================
 is_tm (app T1 T21)
 < search.

Subgoal 3:

Variables: T' T2 Body Ty X
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
IsT : is_tm (app (abs X Ty Body) T2)
Ev : eval (app (abs X Ty Body) T2) T' @
Ev1 : value T2
Ev2 : subst X T2 Body T'
============================
 is_tm T'
 < Is: case IsT.

Subgoal 3:

Variables: T' T2 Body Ty X
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
Ev : eval (app (abs X Ty Body) T2) T' @
Ev1 : value T2
Ev2 : subst X T2 Body T'
Is : is_tm (abs X Ty Body)
Is1 : is_tm T2
============================
 is_tm T'
 < case Is.

Subgoal 3:

Variables: T' T2 Body Ty X
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
Ev : eval (app (abs X Ty Body) T2) T' @
Ev1 : value T2
Ev2 : subst X T2 Body T'
Is1 : is_tm T2
H1 : is_string X
H2 : is_ty Ty
H3 : is_tm Body
============================
 is_tm T'
 < apply subst_is to _ _ _ Ev2.

Subgoal 3:

Variables: T' T2 Body Ty X
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
Ev : eval (app (abs X Ty Body) T2) T' @
Ev1 : value T2
Ev2 : subst X T2 Body T'
Is1 : is_tm T2
H1 : is_string X
H2 : is_ty Ty
H3 : is_tm Body
H4 : is_tm T'
============================
 is_tm T'
 < search.

Subgoal 4:

Variables: T2 T11 T1
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
IsT : is_tm (plus T1 T2)
Ev : eval (plus T1 T2) (plus T11 T2) @
Ev1 : eval T1 T11 *
============================
 is_tm (plus T11 T2)
 < Is: case IsT.

Subgoal 4:

Variables: T2 T11 T1
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
Ev : eval (plus T1 T2) (plus T11 T2) @
Ev1 : eval T1 T11 *
Is : is_tm T1
Is1 : is_tm T2
============================
 is_tm (plus T11 T2)
 < apply IH to _ Ev1.

Subgoal 4:

Variables: T2 T11 T1
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
Ev : eval (plus T1 T2) (plus T11 T2) @
Ev1 : eval T1 T11 *
Is : is_tm T1
Is1 : is_tm T2
H1 : is_tm T11
============================
 is_tm (plus T11 T2)
 < search.

Subgoal 5:

Variables: T21 T1 T2
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
IsT : is_tm (plus T1 T2)
Ev : eval (plus T1 T2) (plus T1 T21) @
Ev1 : value T1
Ev2 : eval T2 T21 *
============================
 is_tm (plus T1 T21)
 < Is: case IsT.

Subgoal 5:

Variables: T21 T1 T2
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
Ev : eval (plus T1 T2) (plus T1 T21) @
Ev1 : value T1
Ev2 : eval T2 T21 *
Is : is_tm T1
Is1 : is_tm T2
============================
 is_tm (plus T1 T21)
 < apply IH to _ Ev2.

Subgoal 5:

Variables: T21 T1 T2
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
Ev : eval (plus T1 T2) (plus T1 T21) @
Ev1 : value T1
Ev2 : eval T2 T21 *
Is : is_tm T1
Is1 : is_tm T2
H1 : is_tm T21
============================
 is_tm (plus T1 T21)
 < search.

Subgoal 6:

Variables: I I2 I1
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
IsT : is_tm (plus (num I1) (num I2))
Ev : eval (plus (num I1) (num I2)) (num I) @
Ev1 : I1 + I2 = I
============================
 is_tm (num I)
 < Is: case IsT.

Subgoal 6:

Variables: I I2 I1
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
Ev : eval (plus (num I1) (num I2)) (num I) @
Ev1 : I1 + I2 = I
Is : is_tm (num I1)
Is1 : is_tm (num I2)
============================
 is_tm (num I)
 < case Is.

Subgoal 6:

Variables: I I2 I1
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
Ev : eval (plus (num I1) (num I2)) (num I) @
Ev1 : I1 + I2 = I
Is1 : is_tm (num I2)
H1 : is_integer I1
============================
 is_tm (num I)
 < case Is1.

Subgoal 6:

Variables: I I2 I1
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
Ev : eval (plus (num I1) (num I2)) (num I) @
Ev1 : I1 + I2 = I
H1 : is_integer I1
H2 : is_integer I2
============================
 is_tm (num I)
 < apply plus_integer_is_integer to _ _ Ev1.

Subgoal 6:

Variables: I I2 I1
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
Ev : eval (plus (num I1) (num I2)) (num I) @
Ev1 : I1 + I2 = I
H1 : is_integer I1
H2 : is_integer I2
H3 : is_integer I
============================
 is_tm (num I)
 < search.

Proof completed.
 < Extensible_Theorem
      subst_unique : forall X R T VA VB,
         SA : subst X R T VA ->
         SB : subst X R T VB ->
         VA = VB
      on SA.

Subgoal 1:

Variables: X R VB Y
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X R (var Y) (var Y) @
SB : subst X R (var Y) VB
SA1 : X = Y -> false
============================
 var Y = VB
 < SB: case SB.

Subgoal 1.1:

Variables: X R Y
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X R (var Y) (var Y) @
SA1 : X = Y -> false
SB : X = Y -> false
============================
 var Y = var Y
 < search.

Subgoal 1.2:

Variables: VB Y
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst Y VB (var Y) (var Y) @
SA1 : Y = Y -> false
============================
 var Y = VB
 < apply SA1 to _.

Subgoal 2:

Variables: X VA VB
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X VA (var X) VA @
SB : subst X VA (var X) VB
============================
 VA = VB
 < SB: case SB.

Subgoal 2.1:

Variables: X VA
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X VA (var X) VA @
SB : X = X -> false
============================
 VA = var X
 < apply SB to _.

Subgoal 2.2:

Variables: X VB
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X VB (var X) VB @
============================
 VB = VB
 < search.

Subgoal 3:

Variables: X R VB S Ty Y B
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X R (abs Y Ty B) (abs Y Ty S) @
SB : subst X R (abs Y Ty B) VB
SA1 : X = Y -> false
SA2 : subst X R B S *
============================
 abs Y Ty S = VB
 < SB: case SB.

Subgoal 3.1:

Variables: X R S Ty Y B S1
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X R (abs Y Ty B) (abs Y Ty S) @
SA1 : X = Y -> false
SA2 : subst X R B S *
SB : X = Y -> false
SB1 : subst X R B S1
============================
 abs Y Ty S = abs Y Ty S1
 < apply IH to SA2 SB1.

Subgoal 3.1:

Variables: X R Ty Y B S1
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X R (abs Y Ty B) (abs Y Ty S1) @
SA1 : X = Y -> false
SA2 : subst X R B S1 *
SB : X = Y -> false
SB1 : subst X R B S1
============================
 abs Y Ty S1 = abs Y Ty S1
 < search.

Subgoal 3.2:

Variables: R S Ty Y B
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst Y R (abs Y Ty B) (abs Y Ty S) @
SA1 : Y = Y -> false
SA2 : subst Y R B S *
============================
 abs Y Ty S = abs Y Ty B
 < apply SA1 to _.

Subgoal 4:

Variables: X R VB B Ty
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X R (abs X Ty B) (abs X Ty B) @
SB : subst X R (abs X Ty B) VB
============================
 abs X Ty B = VB
 < SB: case SB.

Subgoal 4.1:

Variables: X R B Ty S
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X R (abs X Ty B) (abs X Ty B) @
SB : X = X -> false
SB1 : subst X R B S
============================
 abs X Ty B = abs X Ty S
 < apply SB to _.

Subgoal 4.2:

Variables: X R B Ty
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X R (abs X Ty B) (abs X Ty B) @
============================
 abs X Ty B = abs X Ty B
 < search.

Subgoal 5:

Variables: X R VB S2 S1 T2 T1
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X R (app T1 T2) (app S1 S2) @
SB : subst X R (app T1 T2) VB
SA1 : subst X R T1 S1 *
SA2 : subst X R T2 S2 *
============================
 app S1 S2 = VB
 < SB: case SB.

Subgoal 5:

Variables: X R S2 S1 T2 T1 S4 S3
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X R (app T1 T2) (app S1 S2) @
SA1 : subst X R T1 S1 *
SA2 : subst X R T2 S2 *
SB : subst X R T1 S3
SB1 : subst X R T2 S4
============================
 app S1 S2 = app S3 S4
 < apply IH to SA1 SB.

Subgoal 5:

Variables: X R S2 T2 T1 S4 S3
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X R (app T1 T2) (app S3 S2) @
SA1 : subst X R T1 S3 *
SA2 : subst X R T2 S2 *
SB : subst X R T1 S3
SB1 : subst X R T2 S4
============================
 app S3 S2 = app S3 S4
 < apply IH to SA2 SB1.

Subgoal 5:

Variables: X R T2 T1 S4 S3
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X R (app T1 T2) (app S3 S4) @
SA1 : subst X R T1 S3 *
SA2 : subst X R T2 S4 *
SB : subst X R T1 S3
SB1 : subst X R T2 S4
============================
 app S3 S4 = app S3 S4
 < search.

Subgoal 6:

Variables: X R VB I
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X R (num I) (num I) @
SB : subst X R (num I) VB
============================
 num I = VB
 < SB: case SB.

Subgoal 6:

Variables: X R I
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X R (num I) (num I) @
============================
 num I = num I
 < search.

Subgoal 7:

Variables: X R VB S2 S1 T2 T1
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X R (plus T1 T2) (plus S1 S2) @
SB : subst X R (plus T1 T2) VB
SA1 : subst X R T1 S1 *
SA2 : subst X R T2 S2 *
============================
 plus S1 S2 = VB
 < SB: case SB.

Subgoal 7:

Variables: X R S2 S1 T2 T1 S4 S3
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X R (plus T1 T2) (plus S1 S2) @
SA1 : subst X R T1 S1 *
SA2 : subst X R T2 S2 *
SB : subst X R T1 S3
SB1 : subst X R T2 S4
============================
 plus S1 S2 = plus S3 S4
 < apply IH to SA1 SB.

Subgoal 7:

Variables: X R S2 T2 T1 S4 S3
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X R (plus T1 T2) (plus S3 S2) @
SA1 : subst X R T1 S3 *
SA2 : subst X R T2 S2 *
SB : subst X R T1 S3
SB1 : subst X R T2 S4
============================
 plus S3 S2 = plus S3 S4
 < apply IH to SA2 SB1.

Subgoal 7:

Variables: X R T2 T1 S4 S3
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X R (plus T1 T2) (plus S3 S4) @
SA1 : subst X R T1 S3 *
SA2 : subst X R T2 S4 *
SB : subst X R T1 S3
SB1 : subst X R T2 S4
============================
 plus S3 S4 = plus S3 S4
 < search.

Proof completed.
 < Extensible_Theorem
      value_eval_false : forall T V,
         Val : value T ->
         Ev : eval T V ->
         false
      on Val.

Subgoal 1:

Variables: V T1 Ty X
IH : forall T V, value T * -> eval T V -> false
Val : value (abs X Ty T1) @
Ev : eval (abs X Ty T1) V
============================
 false
 < case Ev.

Subgoal 2:

Variables: V I
IH : forall T V, value T * -> eval T V -> false
Val : value (num I) @
Ev : eval (num I) V
============================
 false
 < case Ev.

Proof completed.
 < Extensible_Theorem
      eval_unique : forall T VA VB,
         EvA : eval T VA ->
         EvB : eval T VB ->
         VA = VB
      on EvA.

Subgoal 1:

Variables: VB T2 T11 T1
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (app T1 T2) (app T11 T2) @
EvB : eval (app T1 T2) VB
EvA1 : eval T1 T11 *
============================
 app T11 T2 = VB
 < EvB: case EvB.

Subgoal 1.1:

Variables: T2 T11 T1 T5
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (app T1 T2) (app T11 T2) @
EvA1 : eval T1 T11 *
EvB : eval T1 T5
============================
 app T11 T2 = app T5 T2
 < apply IH to EvA1 EvB.

Subgoal 1.1:

Variables: T2 T1 T5
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (app T1 T2) (app T5 T2) @
EvA1 : eval T1 T5 *
EvB : eval T1 T5
============================
 app T5 T2 = app T5 T2
 < search.

Subgoal 1.2:

Variables: T2 T11 T1 T21
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (app T1 T2) (app T11 T2) @
EvA1 : eval T1 T11 *
EvB : value T1
EvB1 : eval T2 T21
============================
 app T11 T2 = app T1 T21
 < apply value_eval_false to EvB EvA1.

Subgoal 1.3:

Variables: VB T2 T11 Body Ty X
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (app (abs X Ty Body) T2) (app T11 T2) @
EvA1 : eval (abs X Ty Body) T11 *
EvB : value T2
EvB1 : subst X T2 Body VB
============================
 app T11 T2 = VB
 < apply value_eval_false to _ EvA1.

Subgoal 2:

Variables: VB T21 T1 T2
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (app T1 T2) (app T1 T21) @
EvB : eval (app T1 T2) VB
EvA1 : value T1
EvA2 : eval T2 T21 *
============================
 app T1 T21 = VB
 < EvB: case EvB.

Subgoal 2.1:

Variables: T21 T1 T2 T11
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (app T1 T2) (app T1 T21) @
EvA1 : value T1
EvA2 : eval T2 T21 *
EvB : eval T1 T11
============================
 app T1 T21 = app T11 T2
 < apply value_eval_false to EvA1 EvB.

Subgoal 2.2:

Variables: T21 T1 T2 T5
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (app T1 T2) (app T1 T21) @
EvA1 : value T1
EvA2 : eval T2 T21 *
EvB : value T1
EvB1 : eval T2 T5
============================
 app T1 T21 = app T1 T5
 < apply IH to EvA2 EvB1.

Subgoal 2.2:

Variables: T1 T2 T5
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (app T1 T2) (app T1 T5) @
EvA1 : value T1
EvA2 : eval T2 T5 *
EvB : value T1
EvB1 : eval T2 T5
============================
 app T1 T5 = app T1 T5
 < search.

Subgoal 2.3:

Variables: VB T21 T2 Body Ty X
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (app (abs X Ty Body) T2) (app (abs X Ty Body) T21) @
EvA1 : value (abs X Ty Body)
EvA2 : eval T2 T21 *
EvB : value T2
EvB1 : subst X T2 Body VB
============================
 app (abs X Ty Body) T21 = VB
 < apply value_eval_false to EvB EvA2.

Subgoal 3:

Variables: VA VB T2 Body Ty X
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (app (abs X Ty Body) T2) VA @
EvB : eval (app (abs X Ty Body) T2) VB
EvA1 : value T2
EvA2 : subst X T2 Body VA
============================
 VA = VB
 < EvB: case EvB.

Subgoal 3.1:

Variables: VA T2 Body Ty X T11
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (app (abs X Ty Body) T2) VA @
EvA1 : value T2
EvA2 : subst X T2 Body VA
EvB : eval (abs X Ty Body) T11
============================
 VA = app T11 T2
 < case EvB.

Subgoal 3.2:

Variables: VA T2 Body Ty X T21
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (app (abs X Ty Body) T2) VA @
EvA1 : value T2
EvA2 : subst X T2 Body VA
EvB : value (abs X Ty Body)
EvB1 : eval T2 T21
============================
 VA = app (abs X Ty Body) T21
 < apply value_eval_false to EvA1 EvB1.

Subgoal 3.3:

Variables: VA VB T2 Body Ty X
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (app (abs X Ty Body) T2) VA @
EvA1 : value T2
EvA2 : subst X T2 Body VA
EvB : value T2
EvB1 : subst X T2 Body VB
============================
 VA = VB
 < apply subst_unique to EvA2 EvB1.

Subgoal 3.3:

Variables: VB T2 Body Ty X
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (app (abs X Ty Body) T2) VB @
EvA1 : value T2
EvA2 : subst X T2 Body VB
EvB : value T2
EvB1 : subst X T2 Body VB
============================
 VB = VB
 < search.

Subgoal 4:

Variables: VB T2 T11 T1
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (plus T1 T2) (plus T11 T2) @
EvB : eval (plus T1 T2) VB
EvA1 : eval T1 T11 *
============================
 plus T11 T2 = VB
 < EvB: case EvB.

Subgoal 4.1:

Variables: T2 T11 T1 T5
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (plus T1 T2) (plus T11 T2) @
EvA1 : eval T1 T11 *
EvB : eval T1 T5
============================
 plus T11 T2 = plus T5 T2
 < apply IH to EvA1 EvB.

Subgoal 4.1:

Variables: T2 T1 T5
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (plus T1 T2) (plus T5 T2) @
EvA1 : eval T1 T5 *
EvB : eval T1 T5
============================
 plus T5 T2 = plus T5 T2
 < search.

Subgoal 4.2:

Variables: T2 T11 T1 T21
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (plus T1 T2) (plus T11 T2) @
EvA1 : eval T1 T11 *
EvB : value T1
EvB1 : eval T2 T21
============================
 plus T11 T2 = plus T1 T21
 < apply value_eval_false to EvB EvA1.

Subgoal 4.3:

Variables: T11 I I2 I1
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (plus (num I1) (num I2)) (plus T11 (num I2)) @
EvA1 : eval (num I1) T11 *
EvB : I1 + I2 = I
============================
 plus T11 (num I2) = num I
 < case EvA1.

Subgoal 5:

Variables: VB T21 T1 T2
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (plus T1 T2) (plus T1 T21) @
EvB : eval (plus T1 T2) VB
EvA1 : value T1
EvA2 : eval T2 T21 *
============================
 plus T1 T21 = VB
 < EvB: case EvB.

Subgoal 5.1:

Variables: T21 T1 T2 T11
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (plus T1 T2) (plus T1 T21) @
EvA1 : value T1
EvA2 : eval T2 T21 *
EvB : eval T1 T11
============================
 plus T1 T21 = plus T11 T2
 < apply value_eval_false to EvA1 EvB.

Subgoal 5.2:

Variables: T21 T1 T2 T5
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (plus T1 T2) (plus T1 T21) @
EvA1 : value T1
EvA2 : eval T2 T21 *
EvB : value T1
EvB1 : eval T2 T5
============================
 plus T1 T21 = plus T1 T5
 < apply IH to EvA2 EvB1.

Subgoal 5.2:

Variables: T1 T2 T5
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (plus T1 T2) (plus T1 T5) @
EvA1 : value T1
EvA2 : eval T2 T5 *
EvB : value T1
EvB1 : eval T2 T5
============================
 plus T1 T5 = plus T1 T5
 < search.

Subgoal 5.3:

Variables: T21 I I2 I1
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (plus (num I1) (num I2)) (plus (num I1) T21) @
EvA1 : value (num I1)
EvA2 : eval (num I2) T21 *
EvB : I1 + I2 = I
============================
 plus (num I1) T21 = num I
 < case EvA2.

Subgoal 6:

Variables: VB I I2 I1
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (plus (num I1) (num I2)) (num I) @
EvB : eval (plus (num I1) (num I2)) VB
EvA1 : I1 + I2 = I
============================
 num I = VB
 < EvB: case EvB.

Subgoal 6.1:

Variables: I I2 I1 T11
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (plus (num I1) (num I2)) (num I) @
EvA1 : I1 + I2 = I
EvB : eval (num I1) T11
============================
 num I = plus T11 (num I2)
 < case EvB.

Subgoal 6.2:

Variables: I I2 I1 T21
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (plus (num I1) (num I2)) (num I) @
EvA1 : I1 + I2 = I
EvB : value (num I1)
EvB1 : eval (num I2) T21
============================
 num I = plus (num I1) T21
 < case EvB1.

Subgoal 6.3:

Variables: I I2 I1 I5
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (plus (num I1) (num I2)) (num I) @
EvA1 : I1 + I2 = I
EvB : I1 + I2 = I5
============================
 num I = num I5
 < apply plus_integer_unique to EvA1 EvB.

Subgoal 6.3:

Variables: I2 I1 I5
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval (plus (num I1) (num I2)) (num I5) @
EvA1 : I1 + I2 = I5
EvB : I1 + I2 = I5
============================
 num I5 = num I5
 < search.

Proof completed.
 < Extensible_Theorem
      ty_lookup : forall Ctx1 Ctx2 T Ty,
         Ty : typeOf Ctx1 T Ty ->
         L : (forall X XTy,
           lookup Ctx1 X XTy -> lookup Ctx2 X XTy) ->
         typeOf Ctx2 T Ty
      on Ty.

Subgoal 1:

Variables: Ctx1 Ctx2 Ty X
IH : forall Ctx1 Ctx2 T Ty,
       typeOf Ctx1 T Ty * -> (forall X XTy,
         lookup Ctx1 X XTy -> lookup Ctx2 X XTy) -> typeOf Ctx2 T Ty
Ty : typeOf Ctx1 (var X) Ty @
L : forall X XTy, lookup Ctx1 X XTy -> lookup Ctx2 X XTy
Ty1 : lookup Ctx1 X Ty
============================
 typeOf Ctx2 (var X) Ty
 < apply L to Ty1.

Subgoal 1:

Variables: Ctx1 Ctx2 Ty X
IH : forall Ctx1 Ctx2 T Ty,
       typeOf Ctx1 T Ty * -> (forall X XTy,
         lookup Ctx1 X XTy -> lookup Ctx2 X XTy) -> typeOf Ctx2 T Ty
Ty : typeOf Ctx1 (var X) Ty @
L : forall X XTy, lookup Ctx1 X XTy -> lookup Ctx2 X XTy
Ty1 : lookup Ctx1 X Ty
H1 : lookup Ctx2 X Ty
============================
 typeOf Ctx2 (var X) Ty
 < search.

Subgoal 2:

Variables: Ctx1 Ctx2 Ty2 Ty1 Body X
IH : forall Ctx1 Ctx2 T Ty,
       typeOf Ctx1 T Ty * -> (forall X XTy,
         lookup Ctx1 X XTy -> lookup Ctx2 X XTy) -> typeOf Ctx2 T Ty
Ty : typeOf Ctx1 (abs X Ty1 Body) (arrowTy Ty1 Ty2) @
L : forall X XTy, lookup Ctx1 X XTy -> lookup Ctx2 X XTy
Ty1 : typeOf ((X, Ty1)::Ctx1) Body Ty2 *
============================
 typeOf Ctx2 (abs X Ty1 Body) (arrowTy Ty1 Ty2)
 < apply IH to Ty1 _ with
     Ctx2 = (X, Ty1)::Ctx2.

Subgoal 2.1:

Variables: Ctx1 Ctx2 Ty2 Ty1 Body X
IH : forall Ctx1 Ctx2 T Ty,
       typeOf Ctx1 T Ty * -> (forall X XTy,
         lookup Ctx1 X XTy -> lookup Ctx2 X XTy) -> typeOf Ctx2 T Ty
Ty : typeOf Ctx1 (abs X Ty1 Body) (arrowTy Ty1 Ty2) @
L : forall X XTy, lookup Ctx1 X XTy -> lookup Ctx2 X XTy
Ty1 : typeOf ((X, Ty1)::Ctx1) Body Ty2 *
============================
 forall X1 XTy, lookup ((X, Ty1)::Ctx1) X1 XTy -> lookup ((X, Ty1)::Ctx2) X1 XTy
 < intros LkpX.

Subgoal 2.1:

Variables: Ctx1 Ctx2 Ty2 Ty1 Body X X1 XTy
IH : forall Ctx1 Ctx2 T Ty,
       typeOf Ctx1 T Ty * -> (forall X XTy,
         lookup Ctx1 X XTy -> lookup Ctx2 X XTy) -> typeOf Ctx2 T Ty
Ty : typeOf Ctx1 (abs X Ty1 Body) (arrowTy Ty1 Ty2) @
L : forall X XTy, lookup Ctx1 X XTy -> lookup Ctx2 X XTy
Ty1 : typeOf ((X, Ty1)::Ctx1) Body Ty2 *
LkpX : lookup ((X, Ty1)::Ctx1) X1 XTy
============================
 lookup ((X, Ty1)::Ctx2) X1 XTy
 < LkpX: case LkpX.

Subgoal 2.1.1:

Variables: Ctx1 Ctx2 Ty2 Body X1 XTy
IH : forall Ctx1 Ctx2 T Ty,
       typeOf Ctx1 T Ty * -> (forall X XTy,
         lookup Ctx1 X XTy -> lookup Ctx2 X XTy) -> typeOf Ctx2 T Ty
Ty : typeOf Ctx1 (abs X1 XTy Body) (arrowTy XTy Ty2) @
L : forall X XTy, lookup Ctx1 X XTy -> lookup Ctx2 X XTy
Ty1 : typeOf ((X1, XTy)::Ctx1) Body Ty2 *
============================
 lookup ((X1, XTy)::Ctx2) X1 XTy
 < search.

Subgoal 2.1.2:

Variables: Ctx1 Ctx2 Ty2 Ty1 Body X X1 XTy
IH : forall Ctx1 Ctx2 T Ty,
       typeOf Ctx1 T Ty * -> (forall X XTy,
         lookup Ctx1 X XTy -> lookup Ctx2 X XTy) -> typeOf Ctx2 T Ty
Ty : typeOf Ctx1 (abs X Ty1 Body) (arrowTy Ty1 Ty2) @
L : forall X XTy, lookup Ctx1 X XTy -> lookup Ctx2 X XTy
Ty1 : typeOf ((X, Ty1)::Ctx1) Body Ty2 *
LkpX : X = X1 -> false
LkpX1 : lookup Ctx1 X1 XTy
============================
 lookup ((X, Ty1)::Ctx2) X1 XTy
 < apply L to LkpX1.

Subgoal 2.1.2:

Variables: Ctx1 Ctx2 Ty2 Ty1 Body X X1 XTy
IH : forall Ctx1 Ctx2 T Ty,
       typeOf Ctx1 T Ty * -> (forall X XTy,
         lookup Ctx1 X XTy -> lookup Ctx2 X XTy) -> typeOf Ctx2 T Ty
Ty : typeOf Ctx1 (abs X Ty1 Body) (arrowTy Ty1 Ty2) @
L : forall X XTy, lookup Ctx1 X XTy -> lookup Ctx2 X XTy
Ty1 : typeOf ((X, Ty1)::Ctx1) Body Ty2 *
LkpX : X = X1 -> false
LkpX1 : lookup Ctx1 X1 XTy
H1 : lookup Ctx2 X1 XTy
============================
 lookup ((X, Ty1)::Ctx2) X1 XTy
 < search.

Subgoal 2:

Variables: Ctx1 Ctx2 Ty2 Ty1 Body X
IH : forall Ctx1 Ctx2 T Ty,
       typeOf Ctx1 T Ty * -> (forall X XTy,
         lookup Ctx1 X XTy -> lookup Ctx2 X XTy) -> typeOf Ctx2 T Ty
Ty : typeOf Ctx1 (abs X Ty1 Body) (arrowTy Ty1 Ty2) @
L : forall X XTy, lookup Ctx1 X XTy -> lookup Ctx2 X XTy
Ty1 : typeOf ((X, Ty1)::Ctx1) Body Ty2 *
H1 : typeOf ((X, Ty1)::Ctx2) Body Ty2
============================
 typeOf Ctx2 (abs X Ty1 Body) (arrowTy Ty1 Ty2)
 < search.

Subgoal 3:

Variables: Ctx1 Ctx2 Ty Ty1 T2 T1
IH : forall Ctx1 Ctx2 T Ty,
       typeOf Ctx1 T Ty * -> (forall X XTy,
         lookup Ctx1 X XTy -> lookup Ctx2 X XTy) -> typeOf Ctx2 T Ty
Ty : typeOf Ctx1 (app T1 T2) Ty @
L : forall X XTy, lookup Ctx1 X XTy -> lookup Ctx2 X XTy
Ty1 : typeOf Ctx1 T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf Ctx1 T2 Ty1 *
============================
 typeOf Ctx2 (app T1 T2) Ty
 < apply IH to Ty1 L.

Subgoal 3:

Variables: Ctx1 Ctx2 Ty Ty1 T2 T1
IH : forall Ctx1 Ctx2 T Ty,
       typeOf Ctx1 T Ty * -> (forall X XTy,
         lookup Ctx1 X XTy -> lookup Ctx2 X XTy) -> typeOf Ctx2 T Ty
Ty : typeOf Ctx1 (app T1 T2) Ty @
L : forall X XTy, lookup Ctx1 X XTy -> lookup Ctx2 X XTy
Ty1 : typeOf Ctx1 T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf Ctx1 T2 Ty1 *
H1 : typeOf Ctx2 T1 (arrowTy Ty1 Ty)
============================
 typeOf Ctx2 (app T1 T2) Ty
 < apply IH to Ty2 L.

Subgoal 3:

Variables: Ctx1 Ctx2 Ty Ty1 T2 T1
IH : forall Ctx1 Ctx2 T Ty,
       typeOf Ctx1 T Ty * -> (forall X XTy,
         lookup Ctx1 X XTy -> lookup Ctx2 X XTy) -> typeOf Ctx2 T Ty
Ty : typeOf Ctx1 (app T1 T2) Ty @
L : forall X XTy, lookup Ctx1 X XTy -> lookup Ctx2 X XTy
Ty1 : typeOf Ctx1 T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf Ctx1 T2 Ty1 *
H1 : typeOf Ctx2 T1 (arrowTy Ty1 Ty)
H2 : typeOf Ctx2 T2 Ty1
============================
 typeOf Ctx2 (app T1 T2) Ty
 < search.

Subgoal 4:

Variables: Ctx1 Ctx2 I
IH : forall Ctx1 Ctx2 T Ty,
       typeOf Ctx1 T Ty * -> (forall X XTy,
         lookup Ctx1 X XTy -> lookup Ctx2 X XTy) -> typeOf Ctx2 T Ty
Ty : typeOf Ctx1 (num I) intTy @
L : forall X XTy, lookup Ctx1 X XTy -> lookup Ctx2 X XTy
============================
 typeOf Ctx2 (num I) intTy
 < search.

Subgoal 5:

Variables: Ctx1 Ctx2 T2 T1
IH : forall Ctx1 Ctx2 T Ty,
       typeOf Ctx1 T Ty * -> (forall X XTy,
         lookup Ctx1 X XTy -> lookup Ctx2 X XTy) -> typeOf Ctx2 T Ty
Ty : typeOf Ctx1 (plus T1 T2) intTy @
L : forall X XTy, lookup Ctx1 X XTy -> lookup Ctx2 X XTy
Ty1 : typeOf Ctx1 T1 intTy *
Ty2 : typeOf Ctx1 T2 intTy *
============================
 typeOf Ctx2 (plus T1 T2) intTy
 < apply IH to Ty1 L.

Subgoal 5:

Variables: Ctx1 Ctx2 T2 T1
IH : forall Ctx1 Ctx2 T Ty,
       typeOf Ctx1 T Ty * -> (forall X XTy,
         lookup Ctx1 X XTy -> lookup Ctx2 X XTy) -> typeOf Ctx2 T Ty
Ty : typeOf Ctx1 (plus T1 T2) intTy @
L : forall X XTy, lookup Ctx1 X XTy -> lookup Ctx2 X XTy
Ty1 : typeOf Ctx1 T1 intTy *
Ty2 : typeOf Ctx1 T2 intTy *
H1 : typeOf Ctx2 T1 intTy
============================
 typeOf Ctx2 (plus T1 T2) intTy
 < apply IH to Ty2 L.

Subgoal 5:

Variables: Ctx1 Ctx2 T2 T1
IH : forall Ctx1 Ctx2 T Ty,
       typeOf Ctx1 T Ty * -> (forall X XTy,
         lookup Ctx1 X XTy -> lookup Ctx2 X XTy) -> typeOf Ctx2 T Ty
Ty : typeOf Ctx1 (plus T1 T2) intTy @
L : forall X XTy, lookup Ctx1 X XTy -> lookup Ctx2 X XTy
Ty1 : typeOf Ctx1 T1 intTy *
Ty2 : typeOf Ctx1 T2 intTy *
H1 : typeOf Ctx2 T1 intTy
H2 : typeOf Ctx2 T2 intTy
============================
 typeOf Ctx2 (plus T1 T2) intTy
 < search.

Proof completed.
 < Theorem empty_ty_any :
     forall T Ty Ctx, typeOf [] T Ty -> typeOf Ctx T Ty.

============================
 forall T Ty Ctx, typeOf [] T Ty -> typeOf Ctx T Ty
 < intros T.

Variables: T Ty Ctx
T : typeOf [] T Ty
============================
 typeOf Ctx T Ty
 < backchain ty_lookup.

Variables: T Ty Ctx
T : typeOf [] T Ty
============================
 forall X XTy, lookup [] X XTy -> lookup Ctx X XTy
 < intros L.

Variables: T Ty Ctx X XTy
T : typeOf [] T Ty
L : lookup [] X XTy
============================
 lookup Ctx X XTy
 < case L.

Proof completed.
 < Extensible_Theorem
      subst_type_preservation : forall T Ctx X XTy Ty R S,
         TTy : typeOf ((X, XTy)::Ctx) T Ty ->
         S : subst X R T S ->
         RTy : typeOf [] R XTy ->
         typeOf Ctx S Ty
      on S.

Subgoal 1:

Variables: Ctx X XTy Ty R Y
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
TTy : typeOf ((X, XTy)::Ctx) (var Y) Ty
S : subst X R (var Y) (var Y) @
RTy : typeOf [] R XTy
S1 : X = Y -> false
============================
 typeOf Ctx (var Y) Ty
 < Ty: case TTy.

Subgoal 1:

Variables: Ctx X XTy Ty R Y
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (var Y) (var Y) @
RTy : typeOf [] R XTy
S1 : X = Y -> false
Ty : lookup ((X, XTy)::Ctx) Y Ty
============================
 typeOf Ctx (var Y) Ty
 < Lkp: case Ty.

Subgoal 1.1:

Variables: Ctx Ty R Y
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst Y R (var Y) (var Y) @
RTy : typeOf [] R Ty
S1 : Y = Y -> false
============================
 typeOf Ctx (var Y) Ty
 < apply S1 to _.

Subgoal 1.2:

Variables: Ctx X XTy Ty R Y
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (var Y) (var Y) @
RTy : typeOf [] R XTy
S1 : X = Y -> false
Lkp : X = Y -> false
Lkp1 : lookup Ctx Y Ty
============================
 typeOf Ctx (var Y) Ty
 < search.

Subgoal 2:

Variables: Ctx X XTy Ty S
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
TTy : typeOf ((X, XTy)::Ctx) (var X) Ty
S : subst X S (var X) S @
RTy : typeOf [] S XTy
============================
 typeOf Ctx S Ty
 < Ty: case TTy.

Subgoal 2:

Variables: Ctx X XTy Ty S
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X S (var X) S @
RTy : typeOf [] S XTy
Ty : lookup ((X, XTy)::Ctx) X Ty
============================
 typeOf Ctx S Ty
 < L: case Ty.

Subgoal 2.1:

Variables: Ctx X Ty S
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X S (var X) S @
RTy : typeOf [] S Ty
============================
 typeOf Ctx S Ty
 < backchain empty_ty_any.

Subgoal 2.2:

Variables: Ctx X XTy Ty S
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X S (var X) S @
RTy : typeOf [] S XTy
L : X = X -> false
L1 : lookup Ctx X Ty
============================
 typeOf Ctx S Ty
 < apply L to _.

Subgoal 3:

Variables: Ctx X XTy Ty R S1 Ty1 Y B
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
TTy : typeOf ((X, XTy)::Ctx) (abs Y Ty1 B) Ty
S : subst X R (abs Y Ty1 B) (abs Y Ty1 S1) @
RTy : typeOf [] R XTy
S1 : X = Y -> false
S2 : subst X R B S1 *
============================
 typeOf Ctx (abs Y Ty1 S1) Ty
 < Ty: case TTy.

Subgoal 3:

Variables: Ctx X XTy R S1 Ty1 Y B Ty3
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (abs Y Ty1 B) (abs Y Ty1 S1) @
RTy : typeOf [] R XTy
S1 : X = Y -> false
S2 : subst X R B S1 *
Ty : typeOf ((Y, Ty1)::((X, XTy)::Ctx)) B Ty3
============================
 typeOf Ctx (abs Y Ty1 S1) (arrowTy Ty1 Ty3)
 < Ty': apply ty_lookup to Ty _ with
          Ctx2 = (X, XTy)::((Y, Ty1)::Ctx).

Subgoal 3.1:

Variables: Ctx X XTy R S1 Ty1 Y B Ty3
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (abs Y Ty1 B) (abs Y Ty1 S1) @
RTy : typeOf [] R XTy
S1 : X = Y -> false
S2 : subst X R B S1 *
Ty : typeOf ((Y, Ty1)::((X, XTy)::Ctx)) B Ty3
============================
 forall X1 XTy1,
   lookup ((Y, Ty1)::((X, XTy)::Ctx)) X1 XTy1 -> lookup ((X, XTy)::((Y, Ty1)::Ctx)) X1 XTy1
 < intros L.

Subgoal 3.1:

Variables: Ctx X XTy R S1 Ty1 Y B Ty3 X1 XTy1
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (abs Y Ty1 B) (abs Y Ty1 S1) @
RTy : typeOf [] R XTy
S1 : X = Y -> false
S2 : subst X R B S1 *
Ty : typeOf ((Y, Ty1)::((X, XTy)::Ctx)) B Ty3
L : lookup ((Y, Ty1)::((X, XTy)::Ctx)) X1 XTy1
============================
 lookup ((X, XTy)::((Y, Ty1)::Ctx)) X1 XTy1
 < L: case L.

Subgoal 3.1.1:

Variables: Ctx X XTy R S1 B Ty3 X1 XTy1
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (abs X1 XTy1 B) (abs X1 XTy1 S1) @
RTy : typeOf [] R XTy
S1 : X = X1 -> false
S2 : subst X R B S1 *
Ty : typeOf ((X1, XTy1)::((X, XTy)::Ctx)) B Ty3
============================
 lookup ((X, XTy)::((X1, XTy1)::Ctx)) X1 XTy1
 < search.

Subgoal 3.1.2:

Variables: Ctx X XTy R S1 Ty1 Y B Ty3 X1 XTy1
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (abs Y Ty1 B) (abs Y Ty1 S1) @
RTy : typeOf [] R XTy
S1 : X = Y -> false
S2 : subst X R B S1 *
Ty : typeOf ((Y, Ty1)::((X, XTy)::Ctx)) B Ty3
L : Y = X1 -> false
L1 : lookup ((X, XTy)::Ctx) X1 XTy1
============================
 lookup ((X, XTy)::((Y, Ty1)::Ctx)) X1 XTy1
 < L: case L1.

Subgoal 3.1.2.1:

Variables: Ctx R S1 Ty1 Y B Ty3 X1 XTy1
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X1 R (abs Y Ty1 B) (abs Y Ty1 S1) @
RTy : typeOf [] R XTy1
S1 : X1 = Y -> false
S2 : subst X1 R B S1 *
Ty : typeOf ((Y, Ty1)::((X1, XTy1)::Ctx)) B Ty3
L : Y = X1 -> false
============================
 lookup ((X1, XTy1)::((Y, Ty1)::Ctx)) X1 XTy1
 < search.

Subgoal 3.1.2.2:

Variables: Ctx X XTy R S1 Ty1 Y B Ty3 X1 XTy1
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (abs Y Ty1 B) (abs Y Ty1 S1) @
RTy : typeOf [] R XTy
S1 : X = Y -> false
S2 : subst X R B S1 *
Ty : typeOf ((Y, Ty1)::((X, XTy)::Ctx)) B Ty3
L : Y = X1 -> false
L1 : X = X1 -> false
L2 : lookup Ctx X1 XTy1
============================
 lookup ((X, XTy)::((Y, Ty1)::Ctx)) X1 XTy1
 < search.

Subgoal 3:

Variables: Ctx X XTy R S1 Ty1 Y B Ty3
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (abs Y Ty1 B) (abs Y Ty1 S1) @
RTy : typeOf [] R XTy
S1 : X = Y -> false
S2 : subst X R B S1 *
Ty : typeOf ((Y, Ty1)::((X, XTy)::Ctx)) B Ty3
Ty' : typeOf ((X, XTy)::((Y, Ty1)::Ctx)) B Ty3
============================
 typeOf Ctx (abs Y Ty1 S1) (arrowTy Ty1 Ty3)
 < apply IH to Ty' S2 _.

Subgoal 3:

Variables: Ctx X XTy R S1 Ty1 Y B Ty3
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (abs Y Ty1 B) (abs Y Ty1 S1) @
RTy : typeOf [] R XTy
S1 : X = Y -> false
S2 : subst X R B S1 *
Ty : typeOf ((Y, Ty1)::((X, XTy)::Ctx)) B Ty3
Ty' : typeOf ((X, XTy)::((Y, Ty1)::Ctx)) B Ty3
H1 : typeOf ((Y, Ty1)::Ctx) S1 Ty3
============================
 typeOf Ctx (abs Y Ty1 S1) (arrowTy Ty1 Ty3)
 < search.

Subgoal 4:

Variables: Ctx X XTy Ty R B Ty1
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
TTy : typeOf ((X, XTy)::Ctx) (abs X Ty1 B) Ty
S : subst X R (abs X Ty1 B) (abs X Ty1 B) @
RTy : typeOf [] R XTy
============================
 typeOf Ctx (abs X Ty1 B) Ty
 < Ty: case TTy.

Subgoal 4:

Variables: Ctx X XTy R B Ty1 Ty3
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (abs X Ty1 B) (abs X Ty1 B) @
RTy : typeOf [] R XTy
Ty : typeOf ((X, Ty1)::((X, XTy)::Ctx)) B Ty3
============================
 typeOf Ctx (abs X Ty1 B) (arrowTy Ty1 Ty3)
 < apply ty_lookup to Ty _ with
     Ctx2 = (X, Ty1)::Ctx.

Subgoal 4.1:

Variables: Ctx X XTy R B Ty1 Ty3
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (abs X Ty1 B) (abs X Ty1 B) @
RTy : typeOf [] R XTy
Ty : typeOf ((X, Ty1)::((X, XTy)::Ctx)) B Ty3
============================
 forall X1 XTy1,
   lookup ((X, Ty1)::((X, XTy)::Ctx)) X1 XTy1 -> lookup ((X, Ty1)::Ctx) X1 XTy1
 < intros L.

Subgoal 4.1:

Variables: Ctx X XTy R B Ty1 Ty3 X1 XTy1
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (abs X Ty1 B) (abs X Ty1 B) @
RTy : typeOf [] R XTy
Ty : typeOf ((X, Ty1)::((X, XTy)::Ctx)) B Ty3
L : lookup ((X, Ty1)::((X, XTy)::Ctx)) X1 XTy1
============================
 lookup ((X, Ty1)::Ctx) X1 XTy1
 < L: case L.

Subgoal 4.1.1:

Variables: Ctx XTy R B Ty3 X1 XTy1
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X1 R (abs X1 XTy1 B) (abs X1 XTy1 B) @
RTy : typeOf [] R XTy
Ty : typeOf ((X1, XTy1)::((X1, XTy)::Ctx)) B Ty3
============================
 lookup ((X1, XTy1)::Ctx) X1 XTy1
 < search.

Subgoal 4.1.2:

Variables: Ctx X XTy R B Ty1 Ty3 X1 XTy1
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (abs X Ty1 B) (abs X Ty1 B) @
RTy : typeOf [] R XTy
Ty : typeOf ((X, Ty1)::((X, XTy)::Ctx)) B Ty3
L : X = X1 -> false
L1 : lookup ((X, XTy)::Ctx) X1 XTy1
============================
 lookup ((X, Ty1)::Ctx) X1 XTy1
 < L: case L1.

Subgoal 4.1.2.1:

Variables: Ctx R B Ty1 Ty3 X1 XTy1
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X1 R (abs X1 Ty1 B) (abs X1 Ty1 B) @
RTy : typeOf [] R XTy1
Ty : typeOf ((X1, Ty1)::((X1, XTy1)::Ctx)) B Ty3
L : X1 = X1 -> false
============================
 lookup ((X1, Ty1)::Ctx) X1 XTy1
 < apply L to _.

Subgoal 4.1.2.2:

Variables: Ctx X XTy R B Ty1 Ty3 X1 XTy1
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (abs X Ty1 B) (abs X Ty1 B) @
RTy : typeOf [] R XTy
Ty : typeOf ((X, Ty1)::((X, XTy)::Ctx)) B Ty3
L : X = X1 -> false
L1 : X = X1 -> false
L2 : lookup Ctx X1 XTy1
============================
 lookup ((X, Ty1)::Ctx) X1 XTy1
 < search.

Subgoal 4:

Variables: Ctx X XTy R B Ty1 Ty3
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (abs X Ty1 B) (abs X Ty1 B) @
RTy : typeOf [] R XTy
Ty : typeOf ((X, Ty1)::((X, XTy)::Ctx)) B Ty3
H1 : typeOf ((X, Ty1)::Ctx) B Ty3
============================
 typeOf Ctx (abs X Ty1 B) (arrowTy Ty1 Ty3)
 < search.

Subgoal 5:

Variables: Ctx X XTy Ty R S2 S1 T2 T1
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
TTy : typeOf ((X, XTy)::Ctx) (app T1 T2) Ty
S : subst X R (app T1 T2) (app S1 S2) @
RTy : typeOf [] R XTy
S1 : subst X R T1 S1 *
S2 : subst X R T2 S2 *
============================
 typeOf Ctx (app S1 S2) Ty
 < Ty: case TTy.

Subgoal 5:

Variables: Ctx X XTy Ty R S2 S1 T2 T1 Ty1
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (app T1 T2) (app S1 S2) @
RTy : typeOf [] R XTy
S1 : subst X R T1 S1 *
S2 : subst X R T2 S2 *
Ty : typeOf ((X, XTy)::Ctx) T1 (arrowTy Ty1 Ty)
Ty1 : typeOf ((X, XTy)::Ctx) T2 Ty1
============================
 typeOf Ctx (app S1 S2) Ty
 < apply IH to Ty S1 _.

Subgoal 5:

Variables: Ctx X XTy Ty R S2 S1 T2 T1 Ty1
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (app T1 T2) (app S1 S2) @
RTy : typeOf [] R XTy
S1 : subst X R T1 S1 *
S2 : subst X R T2 S2 *
Ty : typeOf ((X, XTy)::Ctx) T1 (arrowTy Ty1 Ty)
Ty1 : typeOf ((X, XTy)::Ctx) T2 Ty1
H1 : typeOf Ctx S1 (arrowTy Ty1 Ty)
============================
 typeOf Ctx (app S1 S2) Ty
 < apply IH to Ty1 S2 _.

Subgoal 5:

Variables: Ctx X XTy Ty R S2 S1 T2 T1 Ty1
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (app T1 T2) (app S1 S2) @
RTy : typeOf [] R XTy
S1 : subst X R T1 S1 *
S2 : subst X R T2 S2 *
Ty : typeOf ((X, XTy)::Ctx) T1 (arrowTy Ty1 Ty)
Ty1 : typeOf ((X, XTy)::Ctx) T2 Ty1
H1 : typeOf Ctx S1 (arrowTy Ty1 Ty)
H2 : typeOf Ctx S2 Ty1
============================
 typeOf Ctx (app S1 S2) Ty
 < search.

Subgoal 6:

Variables: Ctx X XTy Ty R I
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
TTy : typeOf ((X, XTy)::Ctx) (num I) Ty
S : subst X R (num I) (num I) @
RTy : typeOf [] R XTy
============================
 typeOf Ctx (num I) Ty
 < case TTy.

Subgoal 6:

Variables: Ctx X XTy R I
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (num I) (num I) @
RTy : typeOf [] R XTy
============================
 typeOf Ctx (num I) intTy
 < search.

Subgoal 7:

Variables: Ctx X XTy Ty R S2 S1 T2 T1
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
TTy : typeOf ((X, XTy)::Ctx) (plus T1 T2) Ty
S : subst X R (plus T1 T2) (plus S1 S2) @
RTy : typeOf [] R XTy
S1 : subst X R T1 S1 *
S2 : subst X R T2 S2 *
============================
 typeOf Ctx (plus S1 S2) Ty
 < Ty: case TTy.

Subgoal 7:

Variables: Ctx X XTy R S2 S1 T2 T1
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (plus T1 T2) (plus S1 S2) @
RTy : typeOf [] R XTy
S1 : subst X R T1 S1 *
S2 : subst X R T2 S2 *
Ty : typeOf ((X, XTy)::Ctx) T1 intTy
Ty1 : typeOf ((X, XTy)::Ctx) T2 intTy
============================
 typeOf Ctx (plus S1 S2) intTy
 < apply IH to Ty S1 _.

Subgoal 7:

Variables: Ctx X XTy R S2 S1 T2 T1
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (plus T1 T2) (plus S1 S2) @
RTy : typeOf [] R XTy
S1 : subst X R T1 S1 *
S2 : subst X R T2 S2 *
Ty : typeOf ((X, XTy)::Ctx) T1 intTy
Ty1 : typeOf ((X, XTy)::Ctx) T2 intTy
H1 : typeOf Ctx S1 intTy
============================
 typeOf Ctx (plus S1 S2) intTy
 < apply IH to Ty1 S2 _.

Subgoal 7:

Variables: Ctx X XTy R S2 S1 T2 T1
IH : forall T Ctx X XTy Ty R S,
       typeOf ((X, XTy)::Ctx) T Ty -> subst X R T S * -> typeOf [] R XTy -> typeOf Ctx S Ty
S : subst X R (plus T1 T2) (plus S1 S2) @
RTy : typeOf [] R XTy
S1 : subst X R T1 S1 *
S2 : subst X R T2 S2 *
Ty : typeOf ((X, XTy)::Ctx) T1 intTy
Ty1 : typeOf ((X, XTy)::Ctx) T2 intTy
H1 : typeOf Ctx S1 intTy
H2 : typeOf Ctx S2 intTy
============================
 typeOf Ctx (plus S1 S2) intTy
 < search.

Proof completed.
 < Extensible_Theorem
      type_preservation : forall T Ty T',
         Ty : typeOf [] T Ty ->
         Ev : eval T T' ->
         typeOf [] T' Ty
      on Ev.

Subgoal 1:

Variables: Ty T2 T11 T1
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ty : typeOf [] (app T1 T2) Ty
Ev : eval (app T1 T2) (app T11 T2) @
Ev1 : eval T1 T11 *
============================
 typeOf [] (app T11 T2) Ty
 < Ty: case Ty.

Subgoal 1:

Variables: Ty T2 T11 T1 Ty1
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ev : eval (app T1 T2) (app T11 T2) @
Ev1 : eval T1 T11 *
Ty : typeOf [] T1 (arrowTy Ty1 Ty)
Ty1 : typeOf [] T2 Ty1
============================
 typeOf [] (app T11 T2) Ty
 < apply IH to Ty Ev1.

Subgoal 1:

Variables: Ty T2 T11 T1 Ty1
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ev : eval (app T1 T2) (app T11 T2) @
Ev1 : eval T1 T11 *
Ty : typeOf [] T1 (arrowTy Ty1 Ty)
Ty1 : typeOf [] T2 Ty1
H1 : typeOf [] T11 (arrowTy Ty1 Ty)
============================
 typeOf [] (app T11 T2) Ty
 < search.

Subgoal 2:

Variables: Ty T21 T1 T2
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ty : typeOf [] (app T1 T2) Ty
Ev : eval (app T1 T2) (app T1 T21) @
Ev1 : value T1
Ev2 : eval T2 T21 *
============================
 typeOf [] (app T1 T21) Ty
 < Ty: case Ty.

Subgoal 2:

Variables: Ty T21 T1 T2 Ty1
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ev : eval (app T1 T2) (app T1 T21) @
Ev1 : value T1
Ev2 : eval T2 T21 *
Ty : typeOf [] T1 (arrowTy Ty1 Ty)
Ty1 : typeOf [] T2 Ty1
============================
 typeOf [] (app T1 T21) Ty
 < apply IH to Ty1 Ev2.

Subgoal 2:

Variables: Ty T21 T1 T2 Ty1
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ev : eval (app T1 T2) (app T1 T21) @
Ev1 : value T1
Ev2 : eval T2 T21 *
Ty : typeOf [] T1 (arrowTy Ty1 Ty)
Ty1 : typeOf [] T2 Ty1
H1 : typeOf [] T21 Ty1
============================
 typeOf [] (app T1 T21) Ty
 < search.

Subgoal 3:

Variables: Ty T' T2 Body Ty1 X
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ty : typeOf [] (app (abs X Ty1 Body) T2) Ty
Ev : eval (app (abs X Ty1 Body) T2) T' @
Ev1 : value T2
Ev2 : subst X T2 Body T'
============================
 typeOf [] T' Ty
 < Ty: case Ty.

Subgoal 3:

Variables: Ty T' T2 Body Ty1 X Ty2
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ev : eval (app (abs X Ty1 Body) T2) T' @
Ev1 : value T2
Ev2 : subst X T2 Body T'
Ty : typeOf [] (abs X Ty1 Body) (arrowTy Ty2 Ty)
Ty1 : typeOf [] T2 Ty2
============================
 typeOf [] T' Ty
 < Ty: case Ty.

Subgoal 3:

Variables: Ty T' T2 Body X Ty2
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ev : eval (app (abs X Ty2 Body) T2) T' @
Ev1 : value T2
Ev2 : subst X T2 Body T'
Ty1 : typeOf [] T2 Ty2
Ty : typeOf [(X, Ty2)] Body Ty
============================
 typeOf [] T' Ty
 < apply subst_type_preservation to Ty Ev2 Ty1.

Subgoal 3:

Variables: Ty T' T2 Body X Ty2
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ev : eval (app (abs X Ty2 Body) T2) T' @
Ev1 : value T2
Ev2 : subst X T2 Body T'
Ty1 : typeOf [] T2 Ty2
Ty : typeOf [(X, Ty2)] Body Ty
H1 : typeOf [] T' Ty
============================
 typeOf [] T' Ty
 < search.

Subgoal 4:

Variables: Ty T2 T11 T1
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ty : typeOf [] (plus T1 T2) Ty
Ev : eval (plus T1 T2) (plus T11 T2) @
Ev1 : eval T1 T11 *
============================
 typeOf [] (plus T11 T2) Ty
 < Ty: case Ty.

Subgoal 4:

Variables: T2 T11 T1
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ev : eval (plus T1 T2) (plus T11 T2) @
Ev1 : eval T1 T11 *
Ty : typeOf [] T1 intTy
Ty1 : typeOf [] T2 intTy
============================
 typeOf [] (plus T11 T2) intTy
 < apply IH to Ty Ev1.

Subgoal 4:

Variables: T2 T11 T1
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ev : eval (plus T1 T2) (plus T11 T2) @
Ev1 : eval T1 T11 *
Ty : typeOf [] T1 intTy
Ty1 : typeOf [] T2 intTy
H1 : typeOf [] T11 intTy
============================
 typeOf [] (plus T11 T2) intTy
 < search.

Subgoal 5:

Variables: Ty T21 T1 T2
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ty : typeOf [] (plus T1 T2) Ty
Ev : eval (plus T1 T2) (plus T1 T21) @
Ev1 : value T1
Ev2 : eval T2 T21 *
============================
 typeOf [] (plus T1 T21) Ty
 < Ty: case Ty.

Subgoal 5:

Variables: T21 T1 T2
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ev : eval (plus T1 T2) (plus T1 T21) @
Ev1 : value T1
Ev2 : eval T2 T21 *
Ty : typeOf [] T1 intTy
Ty1 : typeOf [] T2 intTy
============================
 typeOf [] (plus T1 T21) intTy
 < apply IH to Ty1 Ev2.

Subgoal 5:

Variables: T21 T1 T2
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ev : eval (plus T1 T2) (plus T1 T21) @
Ev1 : value T1
Ev2 : eval T2 T21 *
Ty : typeOf [] T1 intTy
Ty1 : typeOf [] T2 intTy
H1 : typeOf [] T21 intTy
============================
 typeOf [] (plus T1 T21) intTy
 < search.

Subgoal 6:

Variables: Ty I I2 I1
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ty : typeOf [] (plus (num I1) (num I2)) Ty
Ev : eval (plus (num I1) (num I2)) (num I) @
Ev1 : I1 + I2 = I
============================
 typeOf [] (num I) Ty
 < Ty: case Ty.

Subgoal 6:

Variables: I I2 I1
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ev : eval (plus (num I1) (num I2)) (num I) @
Ev1 : I1 + I2 = I
Ty : typeOf [] (num I1) intTy
Ty1 : typeOf [] (num I2) intTy
============================
 typeOf [] (num I) intTy
 < search.

Proof completed.
 < Extensible_Theorem
      subst_total : forall X R T,
         IsT : is_tm T ->
         IsX : is_string X ->
         exists S,
           subst X R T S
      on IsT.

Subgoal 1:

Variables: X R S
IH : forall X R T, is_tm T * -> is_string X -> exists S, subst X R T S
IsT : is_tm (var S) @
IsX : is_string X
IsT1 : is_string S
============================
 exists S1, subst X R (var S) S1
 < Or: apply is_string_eq_or_not to IsX IsT1.

Subgoal 1:

Variables: X R S
IH : forall X R T, is_tm T * -> is_string X -> exists S, subst X R T S
IsT : is_tm (var S) @
IsX : is_string X
IsT1 : is_string S
Or : X = S \/ (X = S -> false)
============================
 exists S1, subst X R (var S) S1
 < E: case Or.

Subgoal 1.1:

Variables: R S
IH : forall X R T, is_tm T * -> is_string X -> exists S, subst X R T S
IsT : is_tm (var S) @
IsX : is_string S
IsT1 : is_string S
============================
 exists S1, subst S R (var S) S1
 < search.

Subgoal 1.2:

Variables: X R S
IH : forall X R T, is_tm T * -> is_string X -> exists S, subst X R T S
IsT : is_tm (var S) @
IsX : is_string X
IsT1 : is_string S
E : X = S -> false
============================
 exists S1, subst X R (var S) S1
 < search.

Subgoal 2:

Variables: X R Tm Ty S
IH : forall X R T, is_tm T * -> is_string X -> exists S, subst X R T S
IsT : is_tm (abs S Ty Tm) @
IsX : is_string X
IsT1 : is_string S
IsT2 : is_ty Ty
IsT3 : is_tm Tm *
============================
 exists S1, subst X R (abs S Ty Tm) S1
 < Or: apply is_string_eq_or_not to IsX IsT1.

Subgoal 2:

Variables: X R Tm Ty S
IH : forall X R T, is_tm T * -> is_string X -> exists S, subst X R T S
IsT : is_tm (abs S Ty Tm) @
IsX : is_string X
IsT1 : is_string S
IsT2 : is_ty Ty
IsT3 : is_tm Tm *
Or : X = S \/ (X = S -> false)
============================
 exists S1, subst X R (abs S Ty Tm) S1
 < E: case Or.

Subgoal 2.1:

Variables: R Tm Ty S
IH : forall X R T, is_tm T * -> is_string X -> exists S, subst X R T S
IsT : is_tm (abs S Ty Tm) @
IsX : is_string S
IsT1 : is_string S
IsT2 : is_ty Ty
IsT3 : is_tm Tm *
============================
 exists S1, subst S R (abs S Ty Tm) S1
 < search.

Subgoal 2.2:

Variables: X R Tm Ty S
IH : forall X R T, is_tm T * -> is_string X -> exists S, subst X R T S
IsT : is_tm (abs S Ty Tm) @
IsX : is_string X
IsT1 : is_string S
IsT2 : is_ty Ty
IsT3 : is_tm Tm *
E : X = S -> false
============================
 exists S1, subst X R (abs S Ty Tm) S1
 < apply IH to IsT3 IsX with
     R = R.

Subgoal 2.2:

Variables: X R Tm Ty S S1
IH : forall X R T, is_tm T * -> is_string X -> exists S, subst X R T S
IsT : is_tm (abs S Ty Tm) @
IsX : is_string X
IsT1 : is_string S
IsT2 : is_ty Ty
IsT3 : is_tm Tm *
E : X = S -> false
H1 : subst X R Tm S1
============================
 exists S1, subst X R (abs S Ty Tm) S1
 < search.

Subgoal 3:

Variables: X R Tm Tm1
IH : forall X R T, is_tm T * -> is_string X -> exists S, subst X R T S
IsT : is_tm (app Tm1 Tm) @
IsX : is_string X
IsT1 : is_tm Tm1 *
IsT2 : is_tm Tm *
============================
 exists S, subst X R (app Tm1 Tm) S
 < apply IH to IsT1 IsX with
     R = R.

Subgoal 3:

Variables: X R Tm Tm1 S
IH : forall X R T, is_tm T * -> is_string X -> exists S, subst X R T S
IsT : is_tm (app Tm1 Tm) @
IsX : is_string X
IsT1 : is_tm Tm1 *
IsT2 : is_tm Tm *
H1 : subst X R Tm1 S
============================
 exists S, subst X R (app Tm1 Tm) S
 < apply IH to IsT2 IsX with
     R = R.

Subgoal 3:

Variables: X R Tm Tm1 S S1
IH : forall X R T, is_tm T * -> is_string X -> exists S, subst X R T S
IsT : is_tm (app Tm1 Tm) @
IsX : is_string X
IsT1 : is_tm Tm1 *
IsT2 : is_tm Tm *
H1 : subst X R Tm1 S
H2 : subst X R Tm S1
============================
 exists S, subst X R (app Tm1 Tm) S
 < search.

Subgoal 4:

Variables: X R I
IH : forall X R T, is_tm T * -> is_string X -> exists S, subst X R T S
IsT : is_tm (num I) @
IsX : is_string X
IsT1 : is_integer I
============================
 exists S, subst X R (num I) S
 < search.

Subgoal 5:

Variables: X R Tm Tm1
IH : forall X R T, is_tm T * -> is_string X -> exists S, subst X R T S
IsT : is_tm (plus Tm1 Tm) @
IsX : is_string X
IsT1 : is_tm Tm1 *
IsT2 : is_tm Tm *
============================
 exists S, subst X R (plus Tm1 Tm) S
 < apply IH to IsT1 IsX with
     R = R.

Subgoal 5:

Variables: X R Tm Tm1 S
IH : forall X R T, is_tm T * -> is_string X -> exists S, subst X R T S
IsT : is_tm (plus Tm1 Tm) @
IsX : is_string X
IsT1 : is_tm Tm1 *
IsT2 : is_tm Tm *
H1 : subst X R Tm1 S
============================
 exists S, subst X R (plus Tm1 Tm) S
 < apply IH to IsT2 IsX with
     R = R.

Subgoal 5:

Variables: X R Tm Tm1 S S1
IH : forall X R T, is_tm T * -> is_string X -> exists S, subst X R T S
IsT : is_tm (plus Tm1 Tm) @
IsX : is_string X
IsT1 : is_tm Tm1 *
IsT2 : is_tm Tm *
H1 : subst X R Tm1 S
H2 : subst X R Tm S1
============================
 exists S, subst X R (plus Tm1 Tm) S
 < search.

Proof completed.
 < Extensible_Theorem
      canonical_forms : forall V Ty,
         V : value V ->
         Ty : typeOf [] V Ty ->
         canonicalForm Ty V
      on V.

Subgoal 1:

Variables: Ty T Ty1 X
IH : forall V Ty, value V * -> typeOf [] V Ty -> canonicalForm Ty V
V : value (abs X Ty1 T) @
Ty : typeOf [] (abs X Ty1 T) Ty
============================
 canonicalForm Ty (abs X Ty1 T)
 < case Ty.

Subgoal 1:

Variables: T Ty1 X Ty3
IH : forall V Ty, value V * -> typeOf [] V Ty -> canonicalForm Ty V
V : value (abs X Ty1 T) @
H1 : typeOf [(X, Ty1)] T Ty3
============================
 canonicalForm (arrowTy Ty1 Ty3) (abs X Ty1 T)
 < search.

Subgoal 2:

Variables: Ty I
IH : forall V Ty, value V * -> typeOf [] V Ty -> canonicalForm Ty V
V : value (num I) @
Ty : typeOf [] (num I) Ty
============================
 canonicalForm Ty (num I)
 < case Ty.

Subgoal 2:

Variables: I
IH : forall V Ty, value V * -> typeOf [] V Ty -> canonicalForm Ty V
V : value (num I) @
============================
 canonicalForm intTy (num I)
 < search.

Proof completed.
 < Theorem canonical_form_intTy :
     forall V, value V -> typeOf [] V intTy -> exists I, V = num I.

============================
 forall V, value V -> typeOf [] V intTy -> exists I, V = num I
 < intros V Ty.

Variables: V
V : value V
Ty : typeOf [] V intTy
============================
 exists I, V = num I
 < CF: apply canonical_forms to V Ty.

Variables: V
V : value V
Ty : typeOf [] V intTy
CF : canonicalForm intTy V
============================
 exists I, V = num I
 < case CF.

Variables: I
V : value (num I)
Ty : typeOf [] (num I) intTy
============================
 exists I1, num I = num I1
 < search.

Proof completed.
 < Theorem canonical_form_arrowTy :
     forall V Ty1 Ty2,
       value V -> typeOf [] V (arrowTy Ty1 Ty2) -> exists X B, V = abs X Ty1 B.

============================
 forall V Ty1 Ty2,
   value V -> typeOf [] V (arrowTy Ty1 Ty2) -> exists X B, V = abs X Ty1 B
 < intros V Ty.

Variables: V Ty1 Ty2
V : value V
Ty : typeOf [] V (arrowTy Ty1 Ty2)
============================
 exists X B, V = abs X Ty1 B
 < CF: apply canonical_forms to V Ty.

Variables: V Ty1 Ty2
V : value V
Ty : typeOf [] V (arrowTy Ty1 Ty2)
CF : canonicalForm (arrowTy Ty1 Ty2) V
============================
 exists X B, V = abs X Ty1 B
 < case CF.

Variables: Ty1 Ty2 B X
V : value (abs X Ty1 B)
Ty : typeOf [] (abs X Ty1 B) (arrowTy Ty1 Ty2)
============================
 exists X1 B1, abs X Ty1 B = abs X1 Ty1 B1
 < search.

Proof completed.
 < Extensible_Theorem
      progress : forall T Ty,
         IsT : is_tm T ->
         Ty : typeOf [] T Ty ->
         (exists T', eval T T') \/
         value T
      on Ty.

Subgoal 1:

Variables: Ty X
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
IsT : is_tm (var X)
Ty : typeOf [] (var X) Ty @
Ty1 : lookup [] X Ty
============================
 (exists T', eval (var X) T') \/ value (var X)
 < case Ty1.

Subgoal 2:

Variables: Ty2 Ty1 Body X
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
IsT : is_tm (abs X Ty1 Body)
Ty : typeOf [] (abs X Ty1 Body) (arrowTy Ty1 Ty2) @
Ty1 : typeOf [(X, Ty1)] Body Ty2 *
============================
 (exists T', eval (abs X Ty1 Body) T') \/ value (abs X Ty1 Body)
 < search.

Subgoal 3:

Variables: Ty Ty1 T2 T1
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
IsT : is_tm (app T1 T2)
Ty : typeOf [] (app T1 T2) Ty @
Ty1 : typeOf [] T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf [] T2 Ty1 *
============================
 (exists T', eval (app T1 T2) T') \/ value (app T1 T2)
 < Is: case IsT.

Subgoal 3:

Variables: Ty Ty1 T2 T1
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (app T1 T2) Ty @
Ty1 : typeOf [] T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf [] T2 Ty1 *
Is : is_tm T1
Is1 : is_tm T2
============================
 (exists T', eval (app T1 T2) T') \/ value (app T1 T2)
 < Or1: apply IH to _ Ty1.

Subgoal 3:

Variables: Ty Ty1 T2 T1
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (app T1 T2) Ty @
Ty1 : typeOf [] T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf [] T2 Ty1 *
Is : is_tm T1
Is1 : is_tm T2
Or1 : (exists T', eval T1 T') \/ value T1
============================
 (exists T', eval (app T1 T2) T') \/ value (app T1 T2)
 < Or2: apply IH to _ Ty2.

Subgoal 3:

Variables: Ty Ty1 T2 T1
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (app T1 T2) Ty @
Ty1 : typeOf [] T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf [] T2 Ty1 *
Is : is_tm T1
Is1 : is_tm T2
Or1 : (exists T', eval T1 T') \/ value T1
Or2 : (exists T', eval T2 T') \/ value T2
============================
 (exists T', eval (app T1 T2) T') \/ value (app T1 T2)
 < EV1: case Or1.

Subgoal 3.1:

Variables: Ty Ty1 T2 T1 T'
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (app T1 T2) Ty @
Ty1 : typeOf [] T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf [] T2 Ty1 *
Is : is_tm T1
Is1 : is_tm T2
Or2 : (exists T', eval T2 T') \/ value T2
EV1 : eval T1 T'
============================
 (exists T', eval (app T1 T2) T') \/ value (app T1 T2)
 < search.

Subgoal 3.2:

Variables: Ty Ty1 T2 T1
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (app T1 T2) Ty @
Ty1 : typeOf [] T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf [] T2 Ty1 *
Is : is_tm T1
Is1 : is_tm T2
Or2 : (exists T', eval T2 T') \/ value T2
EV1 : value T1
============================
 (exists T', eval (app T1 T2) T') \/ value (app T1 T2)
 < EV2: case Or2.

Subgoal 3.2.1:

Variables: Ty Ty1 T2 T1 T'
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (app T1 T2) Ty @
Ty1 : typeOf [] T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf [] T2 Ty1 *
Is : is_tm T1
Is1 : is_tm T2
EV1 : value T1
EV2 : eval T2 T'
============================
 (exists T', eval (app T1 T2) T') \/ value (app T1 T2)
 < search.

Subgoal 3.2.2:

Variables: Ty Ty1 T2 T1
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (app T1 T2) Ty @
Ty1 : typeOf [] T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf [] T2 Ty1 *
Is : is_tm T1
Is1 : is_tm T2
EV1 : value T1
EV2 : value T2
============================
 (exists T', eval (app T1 T2) T') \/ value (app T1 T2)
 < apply canonical_form_arrowTy to _ Ty1.

Subgoal 3.2.2:

Variables: Ty Ty1 T2 X B
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (app (abs X Ty1 B) T2) Ty @
Ty1 : typeOf [] (abs X Ty1 B) (arrowTy Ty1 Ty) *
Ty2 : typeOf [] T2 Ty1 *
Is : is_tm (abs X Ty1 B)
Is1 : is_tm T2
EV1 : value (abs X Ty1 B)
EV2 : value T2
============================
 (exists T', eval (app (abs X Ty1 B) T2) T') \/ value (app (abs X Ty1 B) T2)
 < IsAbs: case Is.

Subgoal 3.2.2:

Variables: Ty Ty1 T2 X B
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (app (abs X Ty1 B) T2) Ty @
Ty1 : typeOf [] (abs X Ty1 B) (arrowTy Ty1 Ty) *
Ty2 : typeOf [] T2 Ty1 *
Is1 : is_tm T2
EV1 : value (abs X Ty1 B)
EV2 : value T2
IsAbs : is_string X
IsAbs1 : is_ty Ty1
IsAbs2 : is_tm B
============================
 (exists T', eval (app (abs X Ty1 B) T2) T') \/ value (app (abs X Ty1 B) T2)
 < apply subst_total to IsAbs2 IsAbs with
     R = T2.

Subgoal 3.2.2:

Variables: Ty Ty1 T2 X B S
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (app (abs X Ty1 B) T2) Ty @
Ty1 : typeOf [] (abs X Ty1 B) (arrowTy Ty1 Ty) *
Ty2 : typeOf [] T2 Ty1 *
Is1 : is_tm T2
EV1 : value (abs X Ty1 B)
EV2 : value T2
IsAbs : is_string X
IsAbs1 : is_ty Ty1
IsAbs2 : is_tm B
H1 : subst X T2 B S
============================
 (exists T', eval (app (abs X Ty1 B) T2) T') \/ value (app (abs X Ty1 B) T2)
 < search.

Subgoal 4:

Variables: I
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
IsT : is_tm (num I)
Ty : typeOf [] (num I) intTy @
============================
 (exists T', eval (num I) T') \/ value (num I)
 < search.

Subgoal 5:

Variables: T2 T1
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
IsT : is_tm (plus T1 T2)
Ty : typeOf [] (plus T1 T2) intTy @
Ty1 : typeOf [] T1 intTy *
Ty2 : typeOf [] T2 intTy *
============================
 (exists T', eval (plus T1 T2) T') \/ value (plus T1 T2)
 < Is: case IsT.

Subgoal 5:

Variables: T2 T1
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (plus T1 T2) intTy @
Ty1 : typeOf [] T1 intTy *
Ty2 : typeOf [] T2 intTy *
Is : is_tm T1
Is1 : is_tm T2
============================
 (exists T', eval (plus T1 T2) T') \/ value (plus T1 T2)
 < Or1: apply IH to _ Ty1.

Subgoal 5:

Variables: T2 T1
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (plus T1 T2) intTy @
Ty1 : typeOf [] T1 intTy *
Ty2 : typeOf [] T2 intTy *
Is : is_tm T1
Is1 : is_tm T2
Or1 : (exists T', eval T1 T') \/ value T1
============================
 (exists T', eval (plus T1 T2) T') \/ value (plus T1 T2)
 < Or2: apply IH to _ Ty2.

Subgoal 5:

Variables: T2 T1
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (plus T1 T2) intTy @
Ty1 : typeOf [] T1 intTy *
Ty2 : typeOf [] T2 intTy *
Is : is_tm T1
Is1 : is_tm T2
Or1 : (exists T', eval T1 T') \/ value T1
Or2 : (exists T', eval T2 T') \/ value T2
============================
 (exists T', eval (plus T1 T2) T') \/ value (plus T1 T2)
 < EV1: case Or1.

Subgoal 5.1:

Variables: T2 T1 T'
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (plus T1 T2) intTy @
Ty1 : typeOf [] T1 intTy *
Ty2 : typeOf [] T2 intTy *
Is : is_tm T1
Is1 : is_tm T2
Or2 : (exists T', eval T2 T') \/ value T2
EV1 : eval T1 T'
============================
 (exists T', eval (plus T1 T2) T') \/ value (plus T1 T2)
 < search.

Subgoal 5.2:

Variables: T2 T1
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (plus T1 T2) intTy @
Ty1 : typeOf [] T1 intTy *
Ty2 : typeOf [] T2 intTy *
Is : is_tm T1
Is1 : is_tm T2
Or2 : (exists T', eval T2 T') \/ value T2
EV1 : value T1
============================
 (exists T', eval (plus T1 T2) T') \/ value (plus T1 T2)
 < EV2: case Or2.

Subgoal 5.2.1:

Variables: T2 T1 T'
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (plus T1 T2) intTy @
Ty1 : typeOf [] T1 intTy *
Ty2 : typeOf [] T2 intTy *
Is : is_tm T1
Is1 : is_tm T2
EV1 : value T1
EV2 : eval T2 T'
============================
 (exists T', eval (plus T1 T2) T') \/ value (plus T1 T2)
 < search.

Subgoal 5.2.2:

Variables: T2 T1
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (plus T1 T2) intTy @
Ty1 : typeOf [] T1 intTy *
Ty2 : typeOf [] T2 intTy *
Is : is_tm T1
Is1 : is_tm T2
EV1 : value T1
EV2 : value T2
============================
 (exists T', eval (plus T1 T2) T') \/ value (plus T1 T2)
 < apply canonical_form_intTy to _ Ty1.

Subgoal 5.2.2:

Variables: T2 I
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (plus (num I) T2) intTy @
Ty1 : typeOf [] (num I) intTy *
Ty2 : typeOf [] T2 intTy *
Is : is_tm (num I)
Is1 : is_tm T2
EV1 : value (num I)
EV2 : value T2
============================
 (exists T', eval (plus (num I) T2) T') \/ value (plus (num I) T2)
 < Is: case Is.

Subgoal 5.2.2:

Variables: T2 I
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (plus (num I) T2) intTy @
Ty1 : typeOf [] (num I) intTy *
Ty2 : typeOf [] T2 intTy *
Is1 : is_tm T2
EV1 : value (num I)
EV2 : value T2
Is : is_integer I
============================
 (exists T', eval (plus (num I) T2) T') \/ value (plus (num I) T2)
 < apply canonical_form_intTy to _ Ty2.

Subgoal 5.2.2:

Variables: I I1
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (plus (num I) (num I1)) intTy @
Ty1 : typeOf [] (num I) intTy *
Ty2 : typeOf [] (num I1) intTy *
Is1 : is_tm (num I1)
EV1 : value (num I)
EV2 : value (num I1)
Is : is_integer I
============================
 (exists T', eval (plus (num I) (num I1)) T') \/ value (plus (num I) (num I1))
 < Is1: case Is1.

Subgoal 5.2.2:

Variables: I I1
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (plus (num I) (num I1)) intTy @
Ty1 : typeOf [] (num I) intTy *
Ty2 : typeOf [] (num I1) intTy *
EV1 : value (num I)
EV2 : value (num I1)
Is : is_integer I
Is1 : is_integer I1
============================
 (exists T', eval (plus (num I) (num I1)) T') \/ value (plus (num I) (num I1))
 < apply plus_integer_total to Is Is1.

Subgoal 5.2.2:

Variables: I I1 N3
IH : forall T Ty,
       is_tm T -> typeOf [] T Ty * -> (exists T', eval T T') \/ value T
Ty : typeOf [] (plus (num I) (num I1)) intTy @
Ty1 : typeOf [] (num I) intTy *
Ty2 : typeOf [] (num I1) intTy *
EV1 : value (num I)
EV2 : value (num I1)
Is : is_integer I
Is1 : is_integer I1
H1 : I + I1 = N3
============================
 (exists T', eval (plus (num I) (num I1)) T') \/ value (plus (num I) (num I1))
 < search.

Proof completed.
Back to example home