Reasoning Details

 < Module soundX: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.
 < 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.
 < 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.
 < Theorem lookup_desugar_ctx :
     forall Ctx X Ty Ctx',
       lookup Ctx X Ty -> desugar_ctx Ctx Ctx' -> exists Ty',
         lookup Ctx' X Ty' /\ desugar_ty Ty Ty'.

============================
 forall Ctx X Ty Ctx',
   lookup Ctx X Ty -> desugar_ctx Ctx Ctx' -> exists Ty',
     lookup Ctx' X Ty' /\ desugar_ty Ty Ty'
 < induction on 1.

IH : forall Ctx X Ty Ctx',
       lookup Ctx X Ty * -> desugar_ctx Ctx Ctx' -> exists Ty',
         lookup Ctx' X Ty' /\ desugar_ty Ty Ty'
============================
 forall Ctx X Ty Ctx',
   lookup Ctx X Ty @ -> desugar_ctx Ctx Ctx' -> exists Ty',
     lookup Ctx' X Ty' /\ desugar_ty Ty Ty'
 < intros L D.

Variables: Ctx X Ty Ctx'
IH : forall Ctx X Ty Ctx',
       lookup Ctx X Ty * -> desugar_ctx Ctx Ctx' -> exists Ty',
         lookup Ctx' X Ty' /\ desugar_ty Ty Ty'
L : lookup Ctx X Ty @
D : desugar_ctx Ctx Ctx'
============================
 exists Ty', lookup Ctx' X Ty' /\ desugar_ty Ty Ty'
 < L: case L.

Subgoal 1:

Variables: X Ty Ctx' Rest
IH : forall Ctx X Ty Ctx',
       lookup Ctx X Ty * -> desugar_ctx Ctx Ctx' -> exists Ty',
         lookup Ctx' X Ty' /\ desugar_ty Ty Ty'
D : desugar_ctx ((X, Ty)::Rest) Ctx'
============================
 exists Ty', lookup Ctx' X Ty' /\ desugar_ty Ty Ty'
 < case D.

Subgoal 1:

Variables: X Ty Rest DRest DTy
IH : forall Ctx X Ty Ctx',
       lookup Ctx X Ty * -> desugar_ctx Ctx Ctx' -> exists Ty',
         lookup Ctx' X Ty' /\ desugar_ty Ty Ty'
H1 : desugar_ty Ty DTy
H2 : desugar_ctx Rest DRest
============================
 exists Ty', lookup ((X, DTy)::DRest) X Ty' /\ desugar_ty Ty Ty'
 < search.

Subgoal 2:

Variables: X Ty Ctx' Rest V K
IH : forall Ctx X Ty Ctx',
       lookup Ctx X Ty * -> desugar_ctx Ctx Ctx' -> exists Ty',
         lookup Ctx' X Ty' /\ desugar_ty Ty Ty'
D : desugar_ctx ((K, V)::Rest) Ctx'
L : K = X -> false
L1 : lookup Rest X Ty *
============================
 exists Ty', lookup Ctx' X Ty' /\ desugar_ty Ty Ty'
 < D: case D.

Subgoal 2:

Variables: X Ty Rest V K DRest DTy
IH : forall Ctx X Ty Ctx',
       lookup Ctx X Ty * -> desugar_ctx Ctx Ctx' -> exists Ty',
         lookup Ctx' X Ty' /\ desugar_ty Ty Ty'
L : K = X -> false
L1 : lookup Rest X Ty *
D : desugar_ty V DTy
D1 : desugar_ctx Rest DRest
============================
 exists Ty', lookup ((K, DTy)::DRest) X Ty' /\ desugar_ty Ty Ty'
 < apply IH to L1 D1.

Subgoal 2:

Variables: X Ty Rest V K DRest DTy Ty'
IH : forall Ctx X Ty Ctx',
       lookup Ctx X Ty * -> desugar_ctx Ctx Ctx' -> exists Ty',
         lookup Ctx' X Ty' /\ desugar_ty Ty Ty'
L : K = X -> false
L1 : lookup Rest X Ty *
D : desugar_ty V DTy
D1 : desugar_ctx Rest DRest
H1 : lookup DRest X Ty'
H2 : desugar_ty Ty Ty'
============================
 exists Ty', lookup ((K, DTy)::DRest) X Ty' /\ desugar_ty Ty Ty'
 < search.

Proof completed.
 < Theorem desugar_ty_unique :
     forall Ty TyA TyB,
       is_ty Ty -> desugar_ty Ty TyA -> desugar_ty Ty TyB -> TyA = TyB.

============================
 forall Ty TyA TyB,
   is_ty Ty -> desugar_ty Ty TyA -> desugar_ty Ty TyB -> TyA = TyB
 < induction on 2.

IH : forall Ty TyA TyB,
       is_ty Ty -> desugar_ty Ty TyA * -> desugar_ty Ty TyB -> TyA = TyB
============================
 forall Ty TyA TyB,
   is_ty Ty -> desugar_ty Ty TyA @ -> desugar_ty Ty TyB -> TyA = TyB
 < intros IsTy DA DB.

Variables: Ty TyA TyB
IH : forall Ty TyA TyB,
       is_ty Ty -> desugar_ty Ty TyA * -> desugar_ty Ty TyB -> TyA = TyB
IsTy : is_ty Ty
DA : desugar_ty Ty TyA @
DB : desugar_ty Ty TyB
============================
 TyA = TyB
 < DA: case DA.

Subgoal 1:

Variables: TyB DB DA B A
IH : forall Ty TyA TyB,
       is_ty Ty -> desugar_ty Ty TyA * -> desugar_ty Ty TyB -> TyA = TyB
IsTy : is_ty (arrowTy A B)
DB : desugar_ty (arrowTy A B) TyB
DA : desugar_ty A DA *
DA1 : desugar_ty B DB *
============================
 arrowTy DA DB = TyB
 < DB: case DB.

Subgoal 1.1:

Variables: DB DA B A DB1 DA1
IH : forall Ty TyA TyB,
       is_ty Ty -> desugar_ty Ty TyA * -> desugar_ty Ty TyB -> TyA = TyB
IsTy : is_ty (arrowTy A B)
DA : desugar_ty A DA *
DA1 : desugar_ty B DB *
DB : desugar_ty A DA1
DB1 : desugar_ty B DB1
============================
 arrowTy DA DB = arrowTy DA1 DB1
 < case IsTy.

Subgoal 1.1:

Variables: DB DA B A DB1 DA1
IH : forall Ty TyA TyB,
       is_ty Ty -> desugar_ty Ty TyA * -> desugar_ty Ty TyB -> TyA = TyB
DA : desugar_ty A DA *
DA1 : desugar_ty B DB *
DB : desugar_ty A DA1
DB1 : desugar_ty B DB1
H1 : is_ty A
H2 : is_ty B
============================
 arrowTy DA DB = arrowTy DA1 DB1
 < apply IH to _ DA DB.

Subgoal 1.1:

Variables: DB B A DB1 DA1
IH : forall Ty TyA TyB,
       is_ty Ty -> desugar_ty Ty TyA * -> desugar_ty Ty TyB -> TyA = TyB
DA : desugar_ty A DA1 *
DA1 : desugar_ty B DB *
DB : desugar_ty A DA1
DB1 : desugar_ty B DB1
H1 : is_ty A
H2 : is_ty B
============================
 arrowTy DA1 DB = arrowTy DA1 DB1
 < apply IH to _ DA1 DB1.

Subgoal 1.1:

Variables: B A DB1 DA1
IH : forall Ty TyA TyB,
       is_ty Ty -> desugar_ty Ty TyA * -> desugar_ty Ty TyB -> TyA = TyB
DA : desugar_ty A DA1 *
DA1 : desugar_ty B DB1 *
DB : desugar_ty A DA1
DB1 : desugar_ty B DB1
H1 : is_ty A
H2 : is_ty B
============================
 arrowTy DA1 DB1 = arrowTy DA1 DB1
 < search.

Subgoal 1.2:

Variables: TyB DB DA B A Ty_P
IH : forall Ty TyA TyB,
       is_ty Ty -> desugar_ty Ty TyA * -> desugar_ty Ty TyB -> TyA = TyB
IsTy : is_ty (arrowTy A B)
DA : desugar_ty A DA *
DA1 : desugar_ty B DB *
DB : |{ty}- arrowTy A B ~~> Ty_P
DB1 : desugar_ty Ty_P TyB
============================
 arrowTy DA DB = TyB
 < case DB.

Subgoal 2:

Variables: TyB
IH : forall Ty TyA TyB,
       is_ty Ty -> desugar_ty Ty TyA * -> desugar_ty Ty TyB -> TyA = TyB
IsTy : is_ty intTy
DB : desugar_ty intTy TyB
============================
 intTy = TyB
 < DB: case DB.

Subgoal 2.1:

IH : forall Ty TyA TyB,
       is_ty Ty -> desugar_ty Ty TyA * -> desugar_ty Ty TyB -> TyA = TyB
IsTy : is_ty intTy
============================
 intTy = intTy
 < search.

Subgoal 2.2:

Variables: TyB Ty_P
IH : forall Ty TyA TyB,
       is_ty Ty -> desugar_ty Ty TyA * -> desugar_ty Ty TyB -> TyA = TyB
IsTy : is_ty intTy
DB : |{ty}- intTy ~~> Ty_P
DB1 : desugar_ty Ty_P TyB
============================
 intTy = TyB
 < case DB.

Subgoal 3:

Variables: Ty TyA TyB Ty_P
IH : forall Ty TyA TyB,
       is_ty Ty -> desugar_ty Ty TyA * -> desugar_ty Ty TyB -> TyA = TyB
IsTy : is_ty Ty
DB : desugar_ty Ty TyB
DA : |{ty}- Ty ~~> Ty_P
DA1 : desugar_ty Ty_P TyA *
============================
 TyA = TyB
 < DB: case DB.

Subgoal 3.1:

Variables: TyA Ty_P DB DA B A
IH : forall Ty TyA TyB,
       is_ty Ty -> desugar_ty Ty TyA * -> desugar_ty Ty TyB -> TyA = TyB
IsTy : is_ty (arrowTy A B)
DA : |{ty}- arrowTy A B ~~> Ty_P
DA1 : desugar_ty Ty_P TyA *
DB : desugar_ty A DA
DB1 : desugar_ty B DB
============================
 TyA = arrowTy DA DB
 < case DA.

Subgoal 3.2:

Variables: TyA Ty_P
IH : forall Ty TyA TyB,
       is_ty Ty -> desugar_ty Ty TyA * -> desugar_ty Ty TyB -> TyA = TyB
IsTy : is_ty intTy
DA : |{ty}- intTy ~~> Ty_P
DA1 : desugar_ty Ty_P TyA *
============================
 TyA = intTy
 < case DA.

Subgoal 3.3:

Variables: Ty TyA TyB Ty_P Ty_P1
IH : forall Ty TyA TyB,
       is_ty Ty -> desugar_ty Ty TyA * -> desugar_ty Ty TyB -> TyA = TyB
IsTy : is_ty Ty
DA : |{ty}- Ty ~~> Ty_P
DA1 : desugar_ty Ty_P TyA *
DB : |{ty}- Ty ~~> Ty_P1
DB1 : desugar_ty Ty_P1 TyB
============================
 TyA = TyB
 < apply proj_ty_unique to DA DB _.

Subgoal 3.3:

Variables: Ty TyA TyB Ty_P1
IH : forall Ty TyA TyB,
       is_ty Ty -> desugar_ty Ty TyA * -> desugar_ty Ty TyB -> TyA = TyB
IsTy : is_ty Ty
DA : |{ty}- Ty ~~> Ty_P1
DA1 : desugar_ty Ty_P1 TyA *
DB : |{ty}- Ty ~~> Ty_P1
DB1 : desugar_ty Ty_P1 TyB
============================
 TyA = TyB
 < apply proj_ty_is to DA _.

Subgoal 3.3:

Variables: Ty TyA TyB Ty_P1
IH : forall Ty TyA TyB,
       is_ty Ty -> desugar_ty Ty TyA * -> desugar_ty Ty TyB -> TyA = TyB
IsTy : is_ty Ty
DA : |{ty}- Ty ~~> Ty_P1
DA1 : desugar_ty Ty_P1 TyA *
DB : |{ty}- Ty ~~> Ty_P1
DB1 : desugar_ty Ty_P1 TyB
H1 : is_ty Ty_P1
============================
 TyA = TyB
 < apply IH to _ DA1 DB1.

Subgoal 3.3:

Variables: Ty TyB Ty_P1
IH : forall Ty TyA TyB,
       is_ty Ty -> desugar_ty Ty TyA * -> desugar_ty Ty TyB -> TyA = TyB
IsTy : is_ty Ty
DA : |{ty}- Ty ~~> Ty_P1
DA1 : desugar_ty Ty_P1 TyB *
DB : |{ty}- Ty ~~> Ty_P1
DB1 : desugar_ty Ty_P1 TyB
H1 : is_ty Ty_P1
============================
 TyB = TyB
 < search.

Proof completed.
 < Theorem desugar_tm_unique :
     forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA ->
       desugar_tm Ctx T TB -> TA = TB.

============================
 forall Ctx T TA TB,
   is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA -> desugar_tm Ctx T TB ->
   TA = TB
 < induction on 3.

IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
============================
 forall Ctx T TA TB,
   is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA @ -> desugar_tm Ctx T TB ->
   TA = TB
 < intros IsCtx IsT DA DB.

Variables: Ctx T TA TB
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm T
DA : desugar_tm Ctx T TA @
DB : desugar_tm Ctx T TB
============================
 TA = TB
 < DA: case DA.

Subgoal 1:

Variables: Ctx TB X
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (var X)
DB : desugar_tm Ctx (var X) TB
============================
 var X = TB
 < DB: case DB.

Subgoal 1.1:

Variables: Ctx X
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (var X)
============================
 var X = var X
 < search.

Subgoal 1.2:

Variables: Ctx TB X T_P
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (var X)
DB : Ctx |{tm}- var X ~~> T_P
DB1 : desugar_tm Ctx T_P TB
============================
 var X = TB
 < case DB.

Subgoal 2:

Variables: Ctx TB DTm DTy X Tm Ty
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (abs X Ty Tm)
DB : desugar_tm Ctx (abs X Ty Tm) TB
DA : desugar_ty Ty DTy
DA1 : desugar_tm ((X, Ty)::Ctx) Tm DTm *
============================
 abs X DTy DTm = TB
 < DB: case DB.

Subgoal 2.1:

Variables: Ctx DTm DTy X Tm Ty DTm1 DTy1
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (abs X Ty Tm)
DA : desugar_ty Ty DTy
DA1 : desugar_tm ((X, Ty)::Ctx) Tm DTm *
DB : desugar_ty Ty DTy1
DB1 : desugar_tm ((X, Ty)::Ctx) Tm DTm1
============================
 abs X DTy DTm = abs X DTy1 DTm1
 < case IsT.

Subgoal 2.1:

Variables: Ctx DTm DTy X Tm Ty DTm1 DTy1
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
DA : desugar_ty Ty DTy
DA1 : desugar_tm ((X, Ty)::Ctx) Tm DTm *
DB : desugar_ty Ty DTy1
DB1 : desugar_tm ((X, Ty)::Ctx) Tm DTm1
H1 : is_string X
H2 : is_ty Ty
H3 : is_tm Tm
============================
 abs X DTy DTm = abs X DTy1 DTm1
 < apply IH to _ _ DA1 DB1.

Subgoal 2.1:

Variables: Ctx DTy X Tm Ty DTm1 DTy1
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
DA : desugar_ty Ty DTy
DA1 : desugar_tm ((X, Ty)::Ctx) Tm DTm1 *
DB : desugar_ty Ty DTy1
DB1 : desugar_tm ((X, Ty)::Ctx) Tm DTm1
H1 : is_string X
H2 : is_ty Ty
H3 : is_tm Tm
============================
 abs X DTy DTm1 = abs X DTy1 DTm1
 < apply desugar_ty_unique to _ DA DB.

Subgoal 2.1:

Variables: Ctx X Tm Ty DTm1 DTy1
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
DA : desugar_ty Ty DTy1
DA1 : desugar_tm ((X, Ty)::Ctx) Tm DTm1 *
DB : desugar_ty Ty DTy1
DB1 : desugar_tm ((X, Ty)::Ctx) Tm DTm1
H1 : is_string X
H2 : is_ty Ty
H3 : is_tm Tm
============================
 abs X DTy1 DTm1 = abs X DTy1 DTm1
 < search.

Subgoal 2.2:

Variables: Ctx TB DTm DTy X Tm Ty T_P
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (abs X Ty Tm)
DA : desugar_ty Ty DTy
DA1 : desugar_tm ((X, Ty)::Ctx) Tm DTm *
DB : Ctx |{tm}- abs X Ty Tm ~~> T_P
DB1 : desugar_tm Ctx T_P TB
============================
 abs X DTy DTm = TB
 < case DB.

Subgoal 3:

Variables: Ctx TB DB DA B A
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (app A B)
DB : desugar_tm Ctx (app A B) TB
DA : desugar_tm Ctx A DA *
DA1 : desugar_tm Ctx B DB *
============================
 app DA DB = TB
 < DB: case DB.

Subgoal 3.1:

Variables: Ctx DB DA B A DB1 DA1
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (app A B)
DA : desugar_tm Ctx A DA *
DA1 : desugar_tm Ctx B DB *
DB : desugar_tm Ctx A DA1
DB1 : desugar_tm Ctx B DB1
============================
 app DA DB = app DA1 DB1
 < case IsT.

Subgoal 3.1:

Variables: Ctx DB DA B A DB1 DA1
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
DA : desugar_tm Ctx A DA *
DA1 : desugar_tm Ctx B DB *
DB : desugar_tm Ctx A DA1
DB1 : desugar_tm Ctx B DB1
H1 : is_tm A
H2 : is_tm B
============================
 app DA DB = app DA1 DB1
 < apply IH to _ _ DA DB.

Subgoal 3.1:

Variables: Ctx DB B A DB1 DA1
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
DA : desugar_tm Ctx A DA1 *
DA1 : desugar_tm Ctx B DB *
DB : desugar_tm Ctx A DA1
DB1 : desugar_tm Ctx B DB1
H1 : is_tm A
H2 : is_tm B
============================
 app DA1 DB = app DA1 DB1
 < apply IH to _ _ DA1 DB1.

Subgoal 3.1:

Variables: Ctx B A DB1 DA1
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
DA : desugar_tm Ctx A DA1 *
DA1 : desugar_tm Ctx B DB1 *
DB : desugar_tm Ctx A DA1
DB1 : desugar_tm Ctx B DB1
H1 : is_tm A
H2 : is_tm B
============================
 app DA1 DB1 = app DA1 DB1
 < search.

Subgoal 3.2:

Variables: Ctx TB DB DA B A T_P
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (app A B)
DA : desugar_tm Ctx A DA *
DA1 : desugar_tm Ctx B DB *
DB : Ctx |{tm}- app A B ~~> T_P
DB1 : desugar_tm Ctx T_P TB
============================
 app DA DB = TB
 < case DB.

Subgoal 4:

Variables: Ctx TB I
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (num I)
DB : desugar_tm Ctx (num I) TB
============================
 num I = TB
 < DB: case DB.

Subgoal 4.1:

Variables: Ctx I
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (num I)
============================
 num I = num I
 < search.

Subgoal 4.2:

Variables: Ctx TB I T_P
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (num I)
DB : Ctx |{tm}- num I ~~> T_P
DB1 : desugar_tm Ctx T_P TB
============================
 num I = TB
 < case DB.

Subgoal 5:

Variables: Ctx TB DB DA B A
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (plus A B)
DB : desugar_tm Ctx (plus A B) TB
DA : desugar_tm Ctx A DA *
DA1 : desugar_tm Ctx B DB *
============================
 plus DA DB = TB
 < DB: case DB.

Subgoal 5.1:

Variables: Ctx DB DA B A DB1 DA1
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (plus A B)
DA : desugar_tm Ctx A DA *
DA1 : desugar_tm Ctx B DB *
DB : desugar_tm Ctx A DA1
DB1 : desugar_tm Ctx B DB1
============================
 plus DA DB = plus DA1 DB1
 < case IsT.

Subgoal 5.1:

Variables: Ctx DB DA B A DB1 DA1
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
DA : desugar_tm Ctx A DA *
DA1 : desugar_tm Ctx B DB *
DB : desugar_tm Ctx A DA1
DB1 : desugar_tm Ctx B DB1
H1 : is_tm A
H2 : is_tm B
============================
 plus DA DB = plus DA1 DB1
 < apply IH to _ _ DA DB.

Subgoal 5.1:

Variables: Ctx DB B A DB1 DA1
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
DA : desugar_tm Ctx A DA1 *
DA1 : desugar_tm Ctx B DB *
DB : desugar_tm Ctx A DA1
DB1 : desugar_tm Ctx B DB1
H1 : is_tm A
H2 : is_tm B
============================
 plus DA1 DB = plus DA1 DB1
 < apply IH to _ _ DA1 DB1.

Subgoal 5.1:

Variables: Ctx B A DB1 DA1
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
DA : desugar_tm Ctx A DA1 *
DA1 : desugar_tm Ctx B DB1 *
DB : desugar_tm Ctx A DA1
DB1 : desugar_tm Ctx B DB1
H1 : is_tm A
H2 : is_tm B
============================
 plus DA1 DB1 = plus DA1 DB1
 < search.

Subgoal 5.2:

Variables: Ctx TB DB DA B A T_P
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (plus A B)
DA : desugar_tm Ctx A DA *
DA1 : desugar_tm Ctx B DB *
DB : Ctx |{tm}- plus A B ~~> T_P
DB1 : desugar_tm Ctx T_P TB
============================
 plus DA DB = TB
 < case DB.

Subgoal 6:

Variables: Ctx T TA TB T_P
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm T
DB : desugar_tm Ctx T TB
DA : Ctx |{tm}- T ~~> T_P
DA1 : desugar_tm Ctx T_P TA *
============================
 TA = TB
 < DB: case DB.

Subgoal 6.1:

Variables: Ctx TA T_P X
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (var X)
DA : Ctx |{tm}- var X ~~> T_P
DA1 : desugar_tm Ctx T_P TA *
============================
 TA = var X
 < case DA.

Subgoal 6.2:

Variables: Ctx TA T_P DTm DTy X Tm Ty
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (abs X Ty Tm)
DA : Ctx |{tm}- abs X Ty Tm ~~> T_P
DA1 : desugar_tm Ctx T_P TA *
DB : desugar_ty Ty DTy
DB1 : desugar_tm ((X, Ty)::Ctx) Tm DTm
============================
 TA = abs X DTy DTm
 < case DA.

Subgoal 6.3:

Variables: Ctx TA T_P DB DA B A
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (app A B)
DA : Ctx |{tm}- app A B ~~> T_P
DA1 : desugar_tm Ctx T_P TA *
DB : desugar_tm Ctx A DA
DB1 : desugar_tm Ctx B DB
============================
 TA = app DA DB
 < case DA.

Subgoal 6.4:

Variables: Ctx TA T_P I
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (num I)
DA : Ctx |{tm}- num I ~~> T_P
DA1 : desugar_tm Ctx T_P TA *
============================
 TA = num I
 < case DA.

Subgoal 6.5:

Variables: Ctx TA T_P DB DA B A
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm (plus A B)
DA : Ctx |{tm}- plus A B ~~> T_P
DA1 : desugar_tm Ctx T_P TA *
DB : desugar_tm Ctx A DA
DB1 : desugar_tm Ctx B DB
============================
 TA = plus DA DB
 < case DA.

Subgoal 6.6:

Variables: Ctx T TA TB T_P T_P1
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm T
DA : Ctx |{tm}- T ~~> T_P
DA1 : desugar_tm Ctx T_P TA *
DB : Ctx |{tm}- T ~~> T_P1
DB1 : desugar_tm Ctx T_P1 TB
============================
 TA = TB
 < apply proj_tm_unique to DA DB _ _.

Subgoal 6.6:

Variables: Ctx T TA TB T_P1
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm T
DA : Ctx |{tm}- T ~~> T_P1
DA1 : desugar_tm Ctx T_P1 TA *
DB : Ctx |{tm}- T ~~> T_P1
DB1 : desugar_tm Ctx T_P1 TB
============================
 TA = TB
 < apply proj_is to DA _ _.

Subgoal 6.6:

Variables: Ctx T TA TB T_P1
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm T
DA : Ctx |{tm}- T ~~> T_P1
DA1 : desugar_tm Ctx T_P1 TA *
DB : Ctx |{tm}- T ~~> T_P1
DB1 : desugar_tm Ctx T_P1 TB
H1 : is_tm T_P1
============================
 TA = TB
 < apply IH to _ _ DA1 DB1.

Subgoal 6.6:

Variables: Ctx T TB T_P1
IH : forall Ctx T TA TB,
       is_list (is_pair is_string is_ty) Ctx -> is_tm T -> desugar_tm Ctx T TA * ->
       desugar_tm Ctx T TB -> TA = TB
IsCtx : is_list (is_pair is_string is_ty) Ctx
IsT : is_tm T
DA : Ctx |{tm}- T ~~> T_P1
DA1 : desugar_tm Ctx T_P1 TB *
DB : Ctx |{tm}- T ~~> T_P1
DB1 : desugar_tm Ctx T_P1 TB
H1 : is_tm T_P1
============================
 TB = TB
 < search.

Proof completed.
 < Extensible_Theorem
      desugar_ty_exists : forall Ty,
         IsTy : is_ty Ty ->
         exists Ty',
           desugar_ty Ty Ty'
      on IsTy.

Subgoal 1:

Variables: Ty2 Ty1
IH : forall Ty, is_ty Ty * -> exists Ty', desugar_ty Ty Ty'
IsTy : is_ty (arrowTy Ty1 Ty2) @
IsTy1 : is_ty Ty1 *
IsTy2 : is_ty Ty2 *
============================
 exists Ty', desugar_ty (arrowTy Ty1 Ty2) Ty'
 < apply IH to IsTy1.

Subgoal 1:

Variables: Ty2 Ty1 Ty'
IH : forall Ty, is_ty Ty * -> exists Ty', desugar_ty Ty Ty'
IsTy : is_ty (arrowTy Ty1 Ty2) @
IsTy1 : is_ty Ty1 *
IsTy2 : is_ty Ty2 *
H1 : desugar_ty Ty1 Ty'
============================
 exists Ty', desugar_ty (arrowTy Ty1 Ty2) Ty'
 < apply IH to IsTy2.

Subgoal 1:

Variables: Ty2 Ty1 Ty' Ty'1
IH : forall Ty, is_ty Ty * -> exists Ty', desugar_ty Ty Ty'
IsTy : is_ty (arrowTy Ty1 Ty2) @
IsTy1 : is_ty Ty1 *
IsTy2 : is_ty Ty2 *
H1 : desugar_ty Ty1 Ty'
H2 : desugar_ty Ty2 Ty'1
============================
 exists Ty', desugar_ty (arrowTy Ty1 Ty2) Ty'
 < search.

Subgoal 2:

IH : forall Ty, is_ty Ty * -> exists Ty', desugar_ty Ty Ty'
IsTy : is_ty intTy @
============================
 exists Ty', desugar_ty intTy Ty'
 < search.

Proof completed.
 < Define host_is_ty : ty -> prop by
   host_is_ty (arrowTy Ty1 Ty2) :=
     host_is_ty Ty1 /\ host_is_ty Ty2;
   host_is_ty intTy.


 < Define host_is_tm : tm -> prop by
   host_is_tm (var X) :=
     is_string X;
   host_is_tm (abs X Ty B) :=
     (is_string X /\ host_is_ty Ty) /\ host_is_tm B;
   host_is_tm (app A B) :=
     host_is_tm A /\ host_is_tm B;
   host_is_tm (num I) :=
     is_integer I;
   host_is_tm (plus A B) :=
     host_is_tm A /\ host_is_tm B.


 < Theorem desugar_ty_host_is_ty :
     forall Ty DTy, is_ty Ty -> desugar_ty Ty DTy -> host_is_ty DTy.

============================
 forall Ty DTy, is_ty Ty -> desugar_ty Ty DTy -> host_is_ty DTy
 < induction on 2.

IH : forall Ty DTy, is_ty Ty -> desugar_ty Ty DTy * -> host_is_ty DTy
============================
 forall Ty DTy, is_ty Ty -> desugar_ty Ty DTy @ -> host_is_ty DTy
 < intros IsTy DS.

Variables: Ty DTy
IH : forall Ty DTy, is_ty Ty -> desugar_ty Ty DTy * -> host_is_ty DTy
IsTy : is_ty Ty
DS : desugar_ty Ty DTy @
============================
 host_is_ty DTy
 < DS: case DS.

Subgoal 1:

Variables: DB DA B A
IH : forall Ty DTy, is_ty Ty -> desugar_ty Ty DTy * -> host_is_ty DTy
IsTy : is_ty (arrowTy A B)
DS : desugar_ty A DA *
DS1 : desugar_ty B DB *
============================
 host_is_ty (arrowTy DA DB)
 < case IsTy.

Subgoal 1:

Variables: DB DA B A
IH : forall Ty DTy, is_ty Ty -> desugar_ty Ty DTy * -> host_is_ty DTy
DS : desugar_ty A DA *
DS1 : desugar_ty B DB *
H1 : is_ty A
H2 : is_ty B
============================
 host_is_ty (arrowTy DA DB)
 < apply IH to _ DS.

Subgoal 1:

Variables: DB DA B A
IH : forall Ty DTy, is_ty Ty -> desugar_ty Ty DTy * -> host_is_ty DTy
DS : desugar_ty A DA *
DS1 : desugar_ty B DB *
H1 : is_ty A
H2 : is_ty B
H3 : host_is_ty DA
============================
 host_is_ty (arrowTy DA DB)
 < apply IH to _ DS1.

Subgoal 1:

Variables: DB DA B A
IH : forall Ty DTy, is_ty Ty -> desugar_ty Ty DTy * -> host_is_ty DTy
DS : desugar_ty A DA *
DS1 : desugar_ty B DB *
H1 : is_ty A
H2 : is_ty B
H3 : host_is_ty DA
H4 : host_is_ty DB
============================
 host_is_ty (arrowTy DA DB)
 < search.

Subgoal 2:

IH : forall Ty DTy, is_ty Ty -> desugar_ty Ty DTy * -> host_is_ty DTy
IsTy : is_ty intTy
============================
 host_is_ty intTy
 < search.

Subgoal 3:

Variables: Ty DTy Ty_P
IH : forall Ty DTy, is_ty Ty -> desugar_ty Ty DTy * -> host_is_ty DTy
IsTy : is_ty Ty
DS : |{ty}- Ty ~~> Ty_P
DS1 : desugar_ty Ty_P DTy *
============================
 host_is_ty DTy
 < apply proj_ty_is to DS _.

Subgoal 3:

Variables: Ty DTy Ty_P
IH : forall Ty DTy, is_ty Ty -> desugar_ty Ty DTy * -> host_is_ty DTy
IsTy : is_ty Ty
DS : |{ty}- Ty ~~> Ty_P
DS1 : desugar_ty Ty_P DTy *
H1 : is_ty Ty_P
============================
 host_is_ty DTy
 < apply IH to _ DS1.

Subgoal 3:

Variables: Ty DTy Ty_P
IH : forall Ty DTy, is_ty Ty -> desugar_ty Ty DTy * -> host_is_ty DTy
IsTy : is_ty Ty
DS : |{ty}- Ty ~~> Ty_P
DS1 : desugar_ty Ty_P DTy *
H1 : is_ty Ty_P
H2 : host_is_ty DTy
============================
 host_is_ty DTy
 < search.

Proof completed.
 < Theorem desugar_tm_host_is_tm :
     forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT ->
       host_is_tm DT.

============================
 forall Ctx T DT,
   is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT -> host_is_tm DT
 < induction on 3.

IH : forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT * ->
       host_is_tm DT
============================
 forall Ctx T DT,
   is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT @ -> host_is_tm DT
 < intros IsT IsCtx DS.

Variables: Ctx T DT
IH : forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT * ->
       host_is_tm DT
IsT : is_tm T
IsCtx : is_list (is_pair is_string is_ty) Ctx
DS : desugar_tm Ctx T DT @
============================
 host_is_tm DT
 < DS: case DS.

Subgoal 1:

Variables: Ctx X
IH : forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT * ->
       host_is_tm DT
IsT : is_tm (var X)
IsCtx : is_list (is_pair is_string is_ty) Ctx
============================
 host_is_tm (var X)
 < case IsT.

Subgoal 1:

Variables: Ctx X
IH : forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT * ->
       host_is_tm DT
IsCtx : is_list (is_pair is_string is_ty) Ctx
H1 : is_string X
============================
 host_is_tm (var X)
 < search.

Subgoal 2:

Variables: Ctx DTm DTy X Tm Ty
IH : forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT * ->
       host_is_tm DT
IsT : is_tm (abs X Ty Tm)
IsCtx : is_list (is_pair is_string is_ty) Ctx
DS : desugar_ty Ty DTy
DS1 : desugar_tm ((X, Ty)::Ctx) Tm DTm *
============================
 host_is_tm (abs X DTy DTm)
 < case IsT.

Subgoal 2:

Variables: Ctx DTm DTy X Tm Ty
IH : forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT * ->
       host_is_tm DT
IsCtx : is_list (is_pair is_string is_ty) Ctx
DS : desugar_ty Ty DTy
DS1 : desugar_tm ((X, Ty)::Ctx) Tm DTm *
H1 : is_string X
H2 : is_ty Ty
H3 : is_tm Tm
============================
 host_is_tm (abs X DTy DTm)
 < apply desugar_ty_host_is_ty to _ DS.

Subgoal 2:

Variables: Ctx DTm DTy X Tm Ty
IH : forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT * ->
       host_is_tm DT
IsCtx : is_list (is_pair is_string is_ty) Ctx
DS : desugar_ty Ty DTy
DS1 : desugar_tm ((X, Ty)::Ctx) Tm DTm *
H1 : is_string X
H2 : is_ty Ty
H3 : is_tm Tm
H4 : host_is_ty DTy
============================
 host_is_tm (abs X DTy DTm)
 < apply IH to _ _ DS1.

Subgoal 2:

Variables: Ctx DTm DTy X Tm Ty
IH : forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT * ->
       host_is_tm DT
IsCtx : is_list (is_pair is_string is_ty) Ctx
DS : desugar_ty Ty DTy
DS1 : desugar_tm ((X, Ty)::Ctx) Tm DTm *
H1 : is_string X
H2 : is_ty Ty
H3 : is_tm Tm
H4 : host_is_ty DTy
H5 : host_is_tm DTm
============================
 host_is_tm (abs X DTy DTm)
 < search.

Subgoal 3:

Variables: Ctx DB DA B A
IH : forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT * ->
       host_is_tm DT
IsT : is_tm (app A B)
IsCtx : is_list (is_pair is_string is_ty) Ctx
DS : desugar_tm Ctx A DA *
DS1 : desugar_tm Ctx B DB *
============================
 host_is_tm (app DA DB)
 < case IsT.

Subgoal 3:

Variables: Ctx DB DA B A
IH : forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT * ->
       host_is_tm DT
IsCtx : is_list (is_pair is_string is_ty) Ctx
DS : desugar_tm Ctx A DA *
DS1 : desugar_tm Ctx B DB *
H1 : is_tm A
H2 : is_tm B
============================
 host_is_tm (app DA DB)
 < apply IH to _ _ DS.

Subgoal 3:

Variables: Ctx DB DA B A
IH : forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT * ->
       host_is_tm DT
IsCtx : is_list (is_pair is_string is_ty) Ctx
DS : desugar_tm Ctx A DA *
DS1 : desugar_tm Ctx B DB *
H1 : is_tm A
H2 : is_tm B
H3 : host_is_tm DA
============================
 host_is_tm (app DA DB)
 < apply IH to _ _ DS1.

Subgoal 3:

Variables: Ctx DB DA B A
IH : forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT * ->
       host_is_tm DT
IsCtx : is_list (is_pair is_string is_ty) Ctx
DS : desugar_tm Ctx A DA *
DS1 : desugar_tm Ctx B DB *
H1 : is_tm A
H2 : is_tm B
H3 : host_is_tm DA
H4 : host_is_tm DB
============================
 host_is_tm (app DA DB)
 < search.

Subgoal 4:

Variables: Ctx I
IH : forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT * ->
       host_is_tm DT
IsT : is_tm (num I)
IsCtx : is_list (is_pair is_string is_ty) Ctx
============================
 host_is_tm (num I)
 < case IsT.

Subgoal 4:

Variables: Ctx I
IH : forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT * ->
       host_is_tm DT
IsCtx : is_list (is_pair is_string is_ty) Ctx
H1 : is_integer I
============================
 host_is_tm (num I)
 < search.

Subgoal 5:

Variables: Ctx DB DA B A
IH : forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT * ->
       host_is_tm DT
IsT : is_tm (plus A B)
IsCtx : is_list (is_pair is_string is_ty) Ctx
DS : desugar_tm Ctx A DA *
DS1 : desugar_tm Ctx B DB *
============================
 host_is_tm (plus DA DB)
 < case IsT.

Subgoal 5:

Variables: Ctx DB DA B A
IH : forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT * ->
       host_is_tm DT
IsCtx : is_list (is_pair is_string is_ty) Ctx
DS : desugar_tm Ctx A DA *
DS1 : desugar_tm Ctx B DB *
H1 : is_tm A
H2 : is_tm B
============================
 host_is_tm (plus DA DB)
 < apply IH to _ _ DS.

Subgoal 5:

Variables: Ctx DB DA B A
IH : forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT * ->
       host_is_tm DT
IsCtx : is_list (is_pair is_string is_ty) Ctx
DS : desugar_tm Ctx A DA *
DS1 : desugar_tm Ctx B DB *
H1 : is_tm A
H2 : is_tm B
H3 : host_is_tm DA
============================
 host_is_tm (plus DA DB)
 < apply IH to _ _ DS1.

Subgoal 5:

Variables: Ctx DB DA B A
IH : forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT * ->
       host_is_tm DT
IsCtx : is_list (is_pair is_string is_ty) Ctx
DS : desugar_tm Ctx A DA *
DS1 : desugar_tm Ctx B DB *
H1 : is_tm A
H2 : is_tm B
H3 : host_is_tm DA
H4 : host_is_tm DB
============================
 host_is_tm (plus DA DB)
 < search.

Subgoal 6:

Variables: Ctx T DT T_P
IH : forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT * ->
       host_is_tm DT
IsT : is_tm T
IsCtx : is_list (is_pair is_string is_ty) Ctx
DS : Ctx |{tm}- T ~~> T_P
DS1 : desugar_tm Ctx T_P DT *
============================
 host_is_tm DT
 < apply proj_is to DS _ _.

Subgoal 6:

Variables: Ctx T DT T_P
IH : forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT * ->
       host_is_tm DT
IsT : is_tm T
IsCtx : is_list (is_pair is_string is_ty) Ctx
DS : Ctx |{tm}- T ~~> T_P
DS1 : desugar_tm Ctx T_P DT *
H1 : is_tm T_P
============================
 host_is_tm DT
 < apply IH to _ _ DS1.

Subgoal 6:

Variables: Ctx T DT T_P
IH : forall Ctx T DT,
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> desugar_tm Ctx T DT * ->
       host_is_tm DT
IsT : is_tm T
IsCtx : is_list (is_pair is_string is_ty) Ctx
DS : Ctx |{tm}- T ~~> T_P
DS1 : desugar_tm Ctx T_P DT *
H1 : is_tm T_P
H2 : host_is_tm DT
============================
 host_is_tm DT
 < search.

Proof completed.
 < Extensible_Theorem
      desugar_ty_rel : forall Ctx T Ty T' Ty' Ctx',
         IsT : is_tm T ->
         IsCtx : is_list (is_pair is_string is_ty) Ctx ->
         Ty : typeOf Ctx T Ty ->
         DT : desugar_tm Ctx T T' ->
         DTy : desugar_ty Ty Ty' ->
         DCtx : desugar_ctx Ctx Ctx' ->
         typeOf Ctx' T' Ty'
      on Ty.

Subgoal 1:

Variables: Ctx Ty T' Ty' Ctx' X
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsT : is_tm (var X)
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (var X) Ty @
DT : desugar_tm Ctx (var X) T'
DTy : desugar_ty Ty Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : lookup Ctx X Ty
============================
 typeOf Ctx' T' Ty'
 < L: apply lookup_desugar_ctx to Ty1 DCtx.

Subgoal 1:

Variables: Ctx Ty T' Ty' Ctx' X Ty'1
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsT : is_tm (var X)
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (var X) Ty @
DT : desugar_tm Ctx (var X) T'
DTy : desugar_ty Ty Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : lookup Ctx X Ty
L : lookup Ctx' X Ty'1
L1 : desugar_ty Ty Ty'1
============================
 typeOf Ctx' T' Ty'
 < DT: case DT.

Subgoal 1.1:

Variables: Ctx Ty Ty' Ctx' X Ty'1
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsT : is_tm (var X)
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (var X) Ty @
DTy : desugar_ty Ty Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : lookup Ctx X Ty
L : lookup Ctx' X Ty'1
L1 : desugar_ty Ty Ty'1
============================
 typeOf Ctx' (var X) Ty'
 < apply lookup_ty_is to _ Ty1.

Subgoal 1.1:

Variables: Ctx Ty Ty' Ctx' X Ty'1
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsT : is_tm (var X)
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (var X) Ty @
DTy : desugar_ty Ty Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : lookup Ctx X Ty
L : lookup Ctx' X Ty'1
L1 : desugar_ty Ty Ty'1
H1 : is_ty Ty
============================
 typeOf Ctx' (var X) Ty'
 < apply desugar_ty_unique to _ L1 DTy.

Subgoal 1.1:

Variables: Ctx Ty Ty' Ctx' X
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsT : is_tm (var X)
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (var X) Ty @
DTy : desugar_ty Ty Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : lookup Ctx X Ty
L : lookup Ctx' X Ty'
L1 : desugar_ty Ty Ty'
H1 : is_ty Ty
============================
 typeOf Ctx' (var X) Ty'
 < search.

Subgoal 1.2:

Variables: Ctx Ty T' Ty' Ctx' X Ty'1 T_P
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsT : is_tm (var X)
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (var X) Ty @
DTy : desugar_ty Ty Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : lookup Ctx X Ty
L : lookup Ctx' X Ty'1
L1 : desugar_ty Ty Ty'1
DT : Ctx |{tm}- var X ~~> T_P
DT1 : desugar_tm Ctx T_P T'
============================
 typeOf Ctx' T' Ty'
 < case DT.

Subgoal 2:

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

Subgoal 2:

Variables: Ctx T' Ty' Ctx' Ty2 Ty1 Body X
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (abs X Ty1 Body) (arrowTy Ty1 Ty2) @
DT : desugar_tm Ctx (abs X Ty1 Body) T'
DTy : desugar_ty (arrowTy Ty1 Ty2) Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf ((X, Ty1)::Ctx) Body Ty2 *
H1 : is_string X
H2 : is_ty Ty1
H3 : is_tm Body
============================
 typeOf Ctx' T' Ty'
 < DT: case DT.

Subgoal 2.1:

Variables: Ctx Ty' Ctx' Ty2 Ty1 Body X DTm DTy
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (abs X Ty1 Body) (arrowTy Ty1 Ty2) @
DTy : desugar_ty (arrowTy Ty1 Ty2) Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf ((X, Ty1)::Ctx) Body Ty2 *
H1 : is_string X
H2 : is_ty Ty1
H3 : is_tm Body
DT : desugar_ty Ty1 DTy
DT1 : desugar_tm ((X, Ty1)::Ctx) Body DTm
============================
 typeOf Ctx' (abs X DTy DTm) Ty'
 < DTy: case DTy.

Subgoal 2.1.1:

Variables: Ctx Ctx' Ty2 Ty1 Body X DTm DTy DB DA
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (abs X Ty1 Body) (arrowTy Ty1 Ty2) @
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf ((X, Ty1)::Ctx) Body Ty2 *
H1 : is_string X
H2 : is_ty Ty1
H3 : is_tm Body
DT : desugar_ty Ty1 DTy
DT1 : desugar_tm ((X, Ty1)::Ctx) Body DTm
DTy : desugar_ty Ty1 DA
DTy1 : desugar_ty Ty2 DB
============================
 typeOf Ctx' (abs X DTy DTm) (arrowTy DA DB)
 < apply desugar_ty_unique to _ DT DTy.

Subgoal 2.1.1:

Variables: Ctx Ctx' Ty2 Ty1 Body X DTm DB DA
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (abs X Ty1 Body) (arrowTy Ty1 Ty2) @
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf ((X, Ty1)::Ctx) Body Ty2 *
H1 : is_string X
H2 : is_ty Ty1
H3 : is_tm Body
DT : desugar_ty Ty1 DA
DT1 : desugar_tm ((X, Ty1)::Ctx) Body DTm
DTy : desugar_ty Ty1 DA
DTy1 : desugar_ty Ty2 DB
============================
 typeOf Ctx' (abs X DA DTm) (arrowTy DA DB)
 < apply IH to _ _ Ty1 DT1 DTy1 _.

Subgoal 2.1.1:

Variables: Ctx Ctx' Ty2 Ty1 Body X DTm DB DA
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (abs X Ty1 Body) (arrowTy Ty1 Ty2) @
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf ((X, Ty1)::Ctx) Body Ty2 *
H1 : is_string X
H2 : is_ty Ty1
H3 : is_tm Body
DT : desugar_ty Ty1 DA
DT1 : desugar_tm ((X, Ty1)::Ctx) Body DTm
DTy : desugar_ty Ty1 DA
DTy1 : desugar_ty Ty2 DB
H4 : typeOf ((X, DA)::Ctx') DTm DB
============================
 typeOf Ctx' (abs X DA DTm) (arrowTy DA DB)
 < search.

Subgoal 2.1.2:

Variables: Ctx Ty' Ctx' Ty2 Ty1 Body X DTm DTy Ty_P
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (abs X Ty1 Body) (arrowTy Ty1 Ty2) @
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf ((X, Ty1)::Ctx) Body Ty2 *
H1 : is_string X
H2 : is_ty Ty1
H3 : is_tm Body
DT : desugar_ty Ty1 DTy
DT1 : desugar_tm ((X, Ty1)::Ctx) Body DTm
DTy : |{ty}- arrowTy Ty1 Ty2 ~~> Ty_P
DTy1 : desugar_ty Ty_P Ty'
============================
 typeOf Ctx' (abs X DTy DTm) Ty'
 < case DTy.

Subgoal 2.2:

Variables: Ctx T' Ty' Ctx' Ty2 Ty1 Body X T_P
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (abs X Ty1 Body) (arrowTy Ty1 Ty2) @
DTy : desugar_ty (arrowTy Ty1 Ty2) Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf ((X, Ty1)::Ctx) Body Ty2 *
H1 : is_string X
H2 : is_ty Ty1
H3 : is_tm Body
DT : Ctx |{tm}- abs X Ty1 Body ~~> T_P
DT1 : desugar_tm Ctx T_P T'
============================
 typeOf Ctx' T' Ty'
 < case DT.

Subgoal 3:

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

Subgoal 3:

Variables: Ctx Ty T' Ty' Ctx' Ty1 T2 T1
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (app T1 T2) Ty @
DT : desugar_tm Ctx (app T1 T2) T'
DTy : desugar_ty Ty Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf Ctx T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf Ctx T2 Ty1 *
H1 : is_tm T1
H2 : is_tm T2
============================
 typeOf Ctx' T' Ty'
 < DT: case DT.

Subgoal 3.1:

Variables: Ctx Ty Ty' Ctx' Ty1 T2 T1 DB DA
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (app T1 T2) Ty @
DTy : desugar_ty Ty Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf Ctx T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf Ctx T2 Ty1 *
H1 : is_tm T1
H2 : is_tm T2
DT : desugar_tm Ctx T1 DA
DT1 : desugar_tm Ctx T2 DB
============================
 typeOf Ctx' (app DA DB) Ty'
 < IsTy: apply type_is to _ _ Ty1.

Subgoal 3.1:

Variables: Ctx Ty Ty' Ctx' Ty1 T2 T1 DB DA
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (app T1 T2) Ty @
DTy : desugar_ty Ty Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf Ctx T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf Ctx T2 Ty1 *
H1 : is_tm T1
H2 : is_tm T2
DT : desugar_tm Ctx T1 DA
DT1 : desugar_tm Ctx T2 DB
IsTy : is_ty (arrowTy Ty1 Ty)
============================
 typeOf Ctx' (app DA DB) Ty'
 < Is: case IsTy.

Subgoal 3.1:

Variables: Ctx Ty Ty' Ctx' Ty1 T2 T1 DB DA
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (app T1 T2) Ty @
DTy : desugar_ty Ty Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf Ctx T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf Ctx T2 Ty1 *
H1 : is_tm T1
H2 : is_tm T2
DT : desugar_tm Ctx T1 DA
DT1 : desugar_tm Ctx T2 DB
Is : is_ty Ty1
Is1 : is_ty Ty
============================
 typeOf Ctx' (app DA DB) Ty'
 < apply desugar_ty_exists to Is.

Subgoal 3.1:

Variables: Ctx Ty Ty' Ctx' Ty1 T2 T1 DB DA Ty'1
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (app T1 T2) Ty @
DTy : desugar_ty Ty Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf Ctx T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf Ctx T2 Ty1 *
H1 : is_tm T1
H2 : is_tm T2
DT : desugar_tm Ctx T1 DA
DT1 : desugar_tm Ctx T2 DB
Is : is_ty Ty1
Is1 : is_ty Ty
H3 : desugar_ty Ty1 Ty'1
============================
 typeOf Ctx' (app DA DB) Ty'
 < apply desugar_ty_exists to Is1.

Subgoal 3.1:

Variables: Ctx Ty Ty' Ctx' Ty1 T2 T1 DB DA Ty'1 Ty'2
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (app T1 T2) Ty @
DTy : desugar_ty Ty Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf Ctx T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf Ctx T2 Ty1 *
H1 : is_tm T1
H2 : is_tm T2
DT : desugar_tm Ctx T1 DA
DT1 : desugar_tm Ctx T2 DB
Is : is_ty Ty1
Is1 : is_ty Ty
H3 : desugar_ty Ty1 Ty'1
H4 : desugar_ty Ty Ty'2
============================
 typeOf Ctx' (app DA DB) Ty'
 < apply IH to _ _ Ty1 DT _ _.

Subgoal 3.1:

Variables: Ctx Ty Ty' Ctx' Ty1 T2 T1 DB DA Ty'1 Ty'2
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (app T1 T2) Ty @
DTy : desugar_ty Ty Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf Ctx T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf Ctx T2 Ty1 *
H1 : is_tm T1
H2 : is_tm T2
DT : desugar_tm Ctx T1 DA
DT1 : desugar_tm Ctx T2 DB
Is : is_ty Ty1
Is1 : is_ty Ty
H3 : desugar_ty Ty1 Ty'1
H4 : desugar_ty Ty Ty'2
H5 : typeOf Ctx' DA (arrowTy Ty'1 Ty')
============================
 typeOf Ctx' (app DA DB) Ty'
 < apply IH to _ _ Ty2 DT1 _ _.

Subgoal 3.1:

Variables: Ctx Ty Ty' Ctx' Ty1 T2 T1 DB DA Ty'1 Ty'2
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (app T1 T2) Ty @
DTy : desugar_ty Ty Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf Ctx T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf Ctx T2 Ty1 *
H1 : is_tm T1
H2 : is_tm T2
DT : desugar_tm Ctx T1 DA
DT1 : desugar_tm Ctx T2 DB
Is : is_ty Ty1
Is1 : is_ty Ty
H3 : desugar_ty Ty1 Ty'1
H4 : desugar_ty Ty Ty'2
H5 : typeOf Ctx' DA (arrowTy Ty'1 Ty')
H6 : typeOf Ctx' DB Ty'1
============================
 typeOf Ctx' (app DA DB) Ty'
 < search.

Subgoal 3.2:

Variables: Ctx Ty T' Ty' Ctx' Ty1 T2 T1 T_P
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (app T1 T2) Ty @
DTy : desugar_ty Ty Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf Ctx T1 (arrowTy Ty1 Ty) *
Ty2 : typeOf Ctx T2 Ty1 *
H1 : is_tm T1
H2 : is_tm T2
DT : Ctx |{tm}- app T1 T2 ~~> T_P
DT1 : desugar_tm Ctx T_P T'
============================
 typeOf Ctx' T' Ty'
 < case DT.

Subgoal 4:

Variables: Ctx T' Ty' Ctx' I
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsT : is_tm (num I)
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (num I) intTy @
DT : desugar_tm Ctx (num I) T'
DTy : desugar_ty intTy Ty'
DCtx : desugar_ctx Ctx Ctx'
============================
 typeOf Ctx' T' Ty'
 < DT: case DT.

Subgoal 4.1:

Variables: Ctx Ty' Ctx' I
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsT : is_tm (num I)
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (num I) intTy @
DTy : desugar_ty intTy Ty'
DCtx : desugar_ctx Ctx Ctx'
============================
 typeOf Ctx' (num I) Ty'
 < DTy: case DTy.

Subgoal 4.1.1:

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

Subgoal 4.1.2:

Variables: Ctx Ty' Ctx' I Ty_P
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsT : is_tm (num I)
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (num I) intTy @
DCtx : desugar_ctx Ctx Ctx'
DTy : |{ty}- intTy ~~> Ty_P
DTy1 : desugar_ty Ty_P Ty'
============================
 typeOf Ctx' (num I) Ty'
 < case DTy.

Subgoal 4.2:

Variables: Ctx T' Ty' Ctx' I T_P
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsT : is_tm (num I)
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (num I) intTy @
DTy : desugar_ty intTy Ty'
DCtx : desugar_ctx Ctx Ctx'
DT : Ctx |{tm}- num I ~~> T_P
DT1 : desugar_tm Ctx T_P T'
============================
 typeOf Ctx' T' Ty'
 < case DT.

Subgoal 5:

Variables: Ctx T' Ty' Ctx' T2 T1
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsT : is_tm (plus T1 T2)
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (plus T1 T2) intTy @
DT : desugar_tm Ctx (plus T1 T2) T'
DTy : desugar_ty intTy Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf Ctx T1 intTy *
Ty2 : typeOf Ctx T2 intTy *
============================
 typeOf Ctx' T' Ty'
 < case IsT.

Subgoal 5:

Variables: Ctx T' Ty' Ctx' T2 T1
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (plus T1 T2) intTy @
DT : desugar_tm Ctx (plus T1 T2) T'
DTy : desugar_ty intTy Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf Ctx T1 intTy *
Ty2 : typeOf Ctx T2 intTy *
H1 : is_tm T1
H2 : is_tm T2
============================
 typeOf Ctx' T' Ty'
 < DT: case DT.

Subgoal 5.1:

Variables: Ctx Ty' Ctx' T2 T1 DB DA
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (plus T1 T2) intTy @
DTy : desugar_ty intTy Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf Ctx T1 intTy *
Ty2 : typeOf Ctx T2 intTy *
H1 : is_tm T1
H2 : is_tm T2
DT : desugar_tm Ctx T1 DA
DT1 : desugar_tm Ctx T2 DB
============================
 typeOf Ctx' (plus DA DB) Ty'
 < DTy: case DTy.

Subgoal 5.1.1:

Variables: Ctx Ctx' T2 T1 DB DA
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (plus T1 T2) intTy @
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf Ctx T1 intTy *
Ty2 : typeOf Ctx T2 intTy *
H1 : is_tm T1
H2 : is_tm T2
DT : desugar_tm Ctx T1 DA
DT1 : desugar_tm Ctx T2 DB
============================
 typeOf Ctx' (plus DA DB) intTy
 < apply IH to _ _ Ty1 DT _ _.

Subgoal 5.1.1:

Variables: Ctx Ctx' T2 T1 DB DA
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (plus T1 T2) intTy @
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf Ctx T1 intTy *
Ty2 : typeOf Ctx T2 intTy *
H1 : is_tm T1
H2 : is_tm T2
DT : desugar_tm Ctx T1 DA
DT1 : desugar_tm Ctx T2 DB
H3 : typeOf Ctx' DA intTy
============================
 typeOf Ctx' (plus DA DB) intTy
 < apply IH to _ _ Ty2 DT1 _ _.

Subgoal 5.1.1:

Variables: Ctx Ctx' T2 T1 DB DA
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (plus T1 T2) intTy @
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf Ctx T1 intTy *
Ty2 : typeOf Ctx T2 intTy *
H1 : is_tm T1
H2 : is_tm T2
DT : desugar_tm Ctx T1 DA
DT1 : desugar_tm Ctx T2 DB
H3 : typeOf Ctx' DA intTy
H4 : typeOf Ctx' DB intTy
============================
 typeOf Ctx' (plus DA DB) intTy
 < search.

Subgoal 5.1.2:

Variables: Ctx Ty' Ctx' T2 T1 DB DA Ty_P
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (plus T1 T2) intTy @
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf Ctx T1 intTy *
Ty2 : typeOf Ctx T2 intTy *
H1 : is_tm T1
H2 : is_tm T2
DT : desugar_tm Ctx T1 DA
DT1 : desugar_tm Ctx T2 DB
DTy : |{ty}- intTy ~~> Ty_P
DTy1 : desugar_ty Ty_P Ty'
============================
 typeOf Ctx' (plus DA DB) Ty'
 < case DTy.

Subgoal 5.2:

Variables: Ctx T' Ty' Ctx' T2 T1 T_P
IH : forall Ctx T Ty T' Ty' Ctx',
       is_tm T -> is_list (is_pair is_string is_ty) Ctx -> typeOf Ctx T Ty * -> desugar_tm Ctx T T' ->
       desugar_ty Ty Ty' -> desugar_ctx Ctx Ctx' -> typeOf Ctx' T' Ty'
IsCtx : is_list (is_pair is_string is_ty) Ctx
Ty : typeOf Ctx (plus T1 T2) intTy @
DTy : desugar_ty intTy Ty'
DCtx : desugar_ctx Ctx Ctx'
Ty1 : typeOf Ctx T1 intTy *
Ty2 : typeOf Ctx T2 intTy *
H1 : is_tm T1
H2 : is_tm T2
DT : Ctx |{tm}- plus T1 T2 ~~> T_P
DT1 : desugar_tm Ctx T_P T'
============================
 typeOf Ctx' T' Ty'
 < case DT.

Proof completed.
 < Theorem subst_is :
     forall X R T S,
       is_tm T -> is_string X -> is_tm R -> subst X R T S -> is_tm S.

============================
 forall X R T S, is_tm T -> is_string X -> is_tm R -> subst X R T S -> is_tm S
 < induction on 4.

IH : forall X R T S,
       is_tm T -> is_string X -> is_tm R -> subst X R T S * -> is_tm S
============================
 forall X R T S, is_tm T -> is_string X -> is_tm R -> subst X R T S @ -> is_tm S
 < intros IsT IsX IsR S.

Variables: X R T 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 T
IsX : is_string X
IsR : is_tm R
S : subst X R T S @
============================
 is_tm S
 < S: case 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 : 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
============================
 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 : X = Y -> false
S1 : 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 : X = Y -> false
S1 : 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 _ _ _ S1.

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 : X = Y -> false
S1 : 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
============================
 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 T1 S1 *
S1 : 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 T1 S1 *
S1 : subst X R T2 S2 *
Is : is_tm T1
Is1 : is_tm T2
============================
 is_tm (app S1 S2)
 < apply IH to _ _ _ S.

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 T1 S1 *
S1 : 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 _ _ _ 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 T1 S1 *
S1 : 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
============================
 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 T1 S1 *
S1 : 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 T1 S1 *
S1 : subst X R T2 S2 *
Is : is_tm T1
Is1 : is_tm T2
============================
 is_tm (plus S1 S2)
 < apply IH to _ _ _ S.

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 T1 S1 *
S1 : 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 _ _ _ 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 T1 S1 *
S1 : 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.
 < Theorem eval_is :
     forall T T', is_tm T -> eval T T' -> is_tm T'.

============================
 forall T T', is_tm T -> eval T T' -> is_tm T'
 < induction on 2.

IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
============================
 forall T T', is_tm T -> eval T T' @ -> is_tm T'
 < intros IsT Ev.

Variables: T T'
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
IsT : is_tm T
Ev : eval T T' @
============================
 is_tm T'
 < Ev: case 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 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 T1 T11 *
Is : is_tm T1
Is1 : is_tm T2
============================
 is_tm (app T11 T2)
 < apply IH to _ Ev.

Subgoal 1:

Variables: T2 T11 T1
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
Ev : 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 : value T1
Ev1 : 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 : value T1
Ev1 : eval T2 T21 *
Is : is_tm T1
Is1 : is_tm T2
============================
 is_tm (app T1 T21)
 < apply IH to _ Ev1.

Subgoal 2:

Variables: T21 T1 T2
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
Ev : value T1
Ev1 : 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 : value T2
Ev1 : 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 : value T2
Ev1 : 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 : value T2
Ev1 : 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 _ _ _ Ev1.

Subgoal 3:

Variables: T' T2 Body Ty X
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
Ev : value T2
Ev1 : 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 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 T1 T11 *
Is : is_tm T1
Is1 : is_tm T2
============================
 is_tm (plus T11 T2)
 < apply IH to _ Ev.

Subgoal 4:

Variables: T2 T11 T1
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
Ev : 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 : value T1
Ev1 : 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 : value T1
Ev1 : eval T2 T21 *
Is : is_tm T1
Is1 : is_tm T2
============================
 is_tm (plus T1 T21)
 < apply IH to _ Ev1.

Subgoal 5:

Variables: T21 T1 T2
IH : forall T T', is_tm T -> eval T T' * -> is_tm T'
Ev : value T1
Ev1 : 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 : 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 : 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 : 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 : I1 + I2 = I
H1 : is_integer I1
H2 : is_integer I2
============================
 is_tm (num I)
 < apply plus_integer_is_integer to _ _ Ev.

Subgoal 6:

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

Proof completed.
 < Theorem subst_unique :
     forall X R T VA VB, subst X R T VA -> subst X R T VB -> VA = VB.

============================
 forall X R T VA VB, subst X R T VA -> subst X R T VB -> VA = VB
 < induction on 1.

IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
============================
 forall X R T VA VB, subst X R T VA @ -> subst X R T VB -> VA = VB
 < intros SA SB.

Variables: X R T VA VB
IH : forall X R T VA VB, subst X R T VA * -> subst X R T VB -> VA = VB
SA : subst X R T VA @
SB : subst X R T VB
============================
 VA = VB
 < SA: case 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
SB : subst X R (var Y) VB
SA : 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 : 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 : Y = Y -> false
============================
 var Y = VB
 < apply SA 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
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
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
============================
 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
SB : subst X R (abs Y Ty B) VB
SA : X = Y -> false
SA1 : 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 : X = Y -> false
SA1 : 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 SA1 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 : X = Y -> false
SA1 : 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 : Y = Y -> false
SA1 : subst Y R B S *
============================
 abs Y Ty S = abs Y Ty B
 < apply SA 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
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
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
============================
 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
SB : subst X R (app T1 T2) VB
SA : subst X R T1 S1 *
SA1 : 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 T1 S1 *
SA1 : 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 SA 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 T1 S3 *
SA1 : 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 SA1 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 T1 S3 *
SA1 : 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
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
============================
 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
SB : subst X R (plus T1 T2) VB
SA : subst X R T1 S1 *
SA1 : 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 T1 S1 *
SA1 : 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 SA 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 T1 S3 *
SA1 : 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 SA1 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 T1 S3 *
SA1 : 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.
 < Theorem value_eval_false :
     forall T V, value T -> eval T V -> false.

============================
 forall T V, value T -> eval T V -> false
 < intros V Ev.

Variables: T V
V : value T
Ev : eval T V
============================
 false
 < V: case V.

Subgoal 1:

Variables: V T1 Ty X
Ev : eval (abs X Ty T1) V
============================
 false
 < case Ev.

Subgoal 2:

Variables: V I
Ev : eval (num I) V
============================
 false
 < case Ev.

Proof completed.
 < Theorem eval_unique :
     forall T VA VB, eval T VA -> eval T VB -> VA = VB.

============================
 forall T VA VB, eval T VA -> eval T VB -> VA = VB
 < induction on 1.

IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
============================
 forall T VA VB, eval T VA @ -> eval T VB -> VA = VB
 < intros EvA EvB.

Variables: T VA VB
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : eval T VA @
EvB : eval T VB
============================
 VA = VB
 < EvA: case EvA.

Subgoal 1:

Variables: VB T2 T11 T1
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvB : eval (app T1 T2) VB
EvA : 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 T1 T11 *
EvB : eval T1 T5
============================
 app T11 T2 = app T5 T2
 < apply IH to EvA EvB.

Subgoal 1.1:

Variables: T2 T1 T5
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : 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 T1 T11 *
EvB : value T1
EvB1 : eval T2 T21
============================
 app T11 T2 = app T1 T21
 < apply value_eval_false to EvB EvA.

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 (abs X Ty Body) T11 *
EvB : value T2
EvB1 : subst X T2 Body VB
============================
 app T11 T2 = VB
 < apply value_eval_false to _ EvA.

Subgoal 2:

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

Subgoal 2.2:

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

Subgoal 2.2:

Variables: T1 T2 T5
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : value T1
EvA1 : 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 : value (abs X Ty Body)
EvA1 : 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 EvA1.

Subgoal 3:

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

Subgoal 3.3:

Variables: VB T2 Body Ty X
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : value T2
EvA1 : 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
EvB : eval (plus T1 T2) VB
EvA : 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 T1 T11 *
EvB : eval T1 T5
============================
 plus T11 T2 = plus T5 T2
 < apply IH to EvA EvB.

Subgoal 4.1:

Variables: T2 T1 T5
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : 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 T1 T11 *
EvB : value T1
EvB1 : eval T2 T21
============================
 plus T11 T2 = plus T1 T21
 < apply value_eval_false to EvB EvA.

Subgoal 4.3:

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

Subgoal 5:

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

Subgoal 5.2:

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

Subgoal 5.2:

Variables: T1 T2 T5
IH : forall T VA VB, eval T VA * -> eval T VB -> VA = VB
EvA : value T1
EvA1 : 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 : value (num I1)
EvA1 : eval (num I2) T21 *
EvB : I1 + I2 = I
============================
 plus (num I1) T21 = num I
 < case EvA1.

Subgoal 6:

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

Subgoal 6.3:

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

Proof completed.
 < Theorem subst_type_preservation :
     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.

============================
 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
 < induction on 2.

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
============================
 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
 < intros TTy S RTy.

Variables: T Ctx X XTy Ty R 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) T Ty
S : subst X R T S @
RTy : typeOf [] R XTy
============================
 typeOf Ctx S Ty
 < S: case 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
RTy : typeOf [] R XTy
S : 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
RTy : typeOf [] R XTy
S : 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
RTy : typeOf [] R Ty
S : Y = Y -> false
============================
 typeOf Ctx (var Y) Ty
 < apply S 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
RTy : typeOf [] R XTy
S : 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
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
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
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
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
RTy : typeOf [] R XTy
S : X = Y -> false
S1 : 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
RTy : typeOf [] R XTy
S : X = Y -> false
S1 : 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
RTy : typeOf [] R XTy
S : X = Y -> false
S1 : 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
RTy : typeOf [] R XTy
S : X = Y -> false
S1 : 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
RTy : typeOf [] R XTy
S : X = X1 -> false
S1 : 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
RTy : typeOf [] R XTy
S : X = Y -> false
S1 : 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
RTy : typeOf [] R XTy1
S : X1 = Y -> false
S1 : 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
RTy : typeOf [] R XTy
S : X = Y -> false
S1 : 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
RTy : typeOf [] R XTy
S : X = Y -> false
S1 : 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' S1 _.

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
RTy : typeOf [] R XTy
S : X = Y -> false
S1 : 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
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
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
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
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
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
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
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
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
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
RTy : typeOf [] R XTy
S : subst X R T1 S1 *
S1 : 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
RTy : typeOf [] R XTy
S : subst X R T1 S1 *
S1 : 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 S _.

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
RTy : typeOf [] R XTy
S : subst X R T1 S1 *
S1 : 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 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
RTy : typeOf [] R XTy
S : subst X R T1 S1 *
S1 : 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
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
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
RTy : typeOf [] R XTy
S : subst X R T1 S1 *
S1 : 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
RTy : typeOf [] R XTy
S : subst X R T1 S1 *
S1 : 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 S _.

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
RTy : typeOf [] R XTy
S : subst X R T1 S1 *
S1 : 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 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
RTy : typeOf [] R XTy
S : subst X R T1 S1 *
S1 : 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.
 < Theorem type_preservation :
     forall T Ty T', typeOf [] T Ty -> eval T T' -> typeOf [] T' Ty.

============================
 forall T Ty T', typeOf [] T Ty -> eval T T' -> typeOf [] T' Ty
 < induction on 2.

IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
============================
 forall T Ty T', typeOf [] T Ty -> eval T T' @ -> typeOf [] T' Ty
 < intros Ty Ev.

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

Subgoal 1:

Variables: Ty T2 T11 T1 Ty1
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ev : 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 : value T1
Ev1 : 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 : value T1
Ev1 : eval T2 T21 *
Ty : typeOf [] T1 (arrowTy Ty1 Ty)
Ty1 : typeOf [] T2 Ty1
============================
 typeOf [] (app T1 T21) Ty
 < apply IH to Ty1 Ev1.

Subgoal 2:

Variables: Ty T21 T1 T2 Ty1
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ev : value T1
Ev1 : 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 : value T2
Ev1 : 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 : value T2
Ev1 : 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 : value T2
Ev1 : subst X T2 Body T'
Ty1 : typeOf [] T2 Ty2
Ty : typeOf [(X, Ty2)] Body Ty
============================
 typeOf [] T' Ty
 < apply subst_type_preservation to Ty Ev1 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 : value T2
Ev1 : 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 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 T1 T11 *
Ty : typeOf [] T1 intTy
Ty1 : typeOf [] T2 intTy
============================
 typeOf [] (plus T11 T2) intTy
 < apply IH to Ty Ev.

Subgoal 4:

Variables: T2 T11 T1
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ev : 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 : value T1
Ev1 : 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 : value T1
Ev1 : eval T2 T21 *
Ty : typeOf [] T1 intTy
Ty1 : typeOf [] T2 intTy
============================
 typeOf [] (plus T1 T21) intTy
 < apply IH to Ty1 Ev1.

Subgoal 5:

Variables: T21 T1 T2
IH : forall T Ty T', typeOf [] T Ty -> eval T T' * -> typeOf [] T' Ty
Ev : value T1
Ev1 : 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 : 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 : I1 + I2 = I
Ty : typeOf [] (num I1) intTy
Ty1 : typeOf [] (num I2) intTy
============================
 typeOf [] (num I) intTy
 < search.

Proof completed.
 < Theorem subst_total :
     forall X R T, host_is_tm T -> is_string X -> exists S, subst X R T S.

============================
 forall X R T, host_is_tm T -> is_string X -> exists S, subst X R T S
 < induction on 1.

IH : forall X R T, host_is_tm T * -> is_string X -> exists S, subst X R T S
============================
 forall X R T, host_is_tm T @ -> is_string X -> exists S, subst X R T S
 < intros IsT IsX.

Variables: X R T
IH : forall X R T, host_is_tm T * -> is_string X -> exists S, subst X R T S
IsT : host_is_tm T @
IsX : is_string X
============================
 exists S, subst X R T S
 < IsT: case IsT.

Subgoal 1:

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

Subgoal 1:

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

Subgoal 1.1:

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

Subgoal 1.2:

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

Subgoal 2:

Variables: X R B Ty X1
IH : forall X R T, host_is_tm T * -> is_string X -> exists S, subst X R T S
IsX : is_string X
IsT : is_string X1
IsT1 : host_is_ty Ty
IsT2 : host_is_tm B *
============================
 exists S, subst X R (abs X1 Ty B) S
 < Or: apply is_string_eq_or_not to IsX IsT.

Subgoal 2:

Variables: X R B Ty X1
IH : forall X R T, host_is_tm T * -> is_string X -> exists S, subst X R T S
IsX : is_string X
IsT : is_string X1
IsT1 : host_is_ty Ty
IsT2 : host_is_tm B *
Or : X = X1 \/ (X = X1 -> false)
============================
 exists S, subst X R (abs X1 Ty B) S
 < E: case Or.

Subgoal 2.1:

Variables: R B Ty X1
IH : forall X R T, host_is_tm T * -> is_string X -> exists S, subst X R T S
IsX : is_string X1
IsT : is_string X1
IsT1 : host_is_ty Ty
IsT2 : host_is_tm B *
============================
 exists S, subst X1 R (abs X1 Ty B) S
 < search.

Subgoal 2.2:

Variables: X R B Ty X1
IH : forall X R T, host_is_tm T * -> is_string X -> exists S, subst X R T S
IsX : is_string X
IsT : is_string X1
IsT1 : host_is_ty Ty
IsT2 : host_is_tm B *
E : X = X1 -> false
============================
 exists S, subst X R (abs X1 Ty B) S
 < apply IH to IsT2 IsX with
     R = R.

Subgoal 2.2:

Variables: X R B Ty X1 S
IH : forall X R T, host_is_tm T * -> is_string X -> exists S, subst X R T S
IsX : is_string X
IsT : is_string X1
IsT1 : host_is_ty Ty
IsT2 : host_is_tm B *
E : X = X1 -> false
H1 : subst X R B S
============================
 exists S, subst X R (abs X1 Ty B) S
 < search.

Subgoal 3:

Variables: X R B A
IH : forall X R T, host_is_tm T * -> is_string X -> exists S, subst X R T S
IsX : is_string X
IsT : host_is_tm A *
IsT1 : host_is_tm B *
============================
 exists S, subst X R (app A B) S
 < apply IH to IsT IsX with
     R = R.

Subgoal 3:

Variables: X R B A S
IH : forall X R T, host_is_tm T * -> is_string X -> exists S, subst X R T S
IsX : is_string X
IsT : host_is_tm A *
IsT1 : host_is_tm B *
H1 : subst X R A S
============================
 exists S, subst X R (app A B) S
 < apply IH to IsT1 IsX with
     R = R.

Subgoal 3:

Variables: X R B A S S1
IH : forall X R T, host_is_tm T * -> is_string X -> exists S, subst X R T S
IsX : is_string X
IsT : host_is_tm A *
IsT1 : host_is_tm B *
H1 : subst X R A S
H2 : subst X R B S1
============================
 exists S, subst X R (app A B) S
 < search.

Subgoal 4:

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

Subgoal 5:

Variables: X R B A
IH : forall X R T, host_is_tm T * -> is_string X -> exists S, subst X R T S
IsX : is_string X
IsT : host_is_tm A *
IsT1 : host_is_tm B *
============================
 exists S, subst X R (plus A B) S
 < apply IH to IsT IsX with
     R = R.

Subgoal 5:

Variables: X R B A S
IH : forall X R T, host_is_tm T * -> is_string X -> exists S, subst X R T S
IsX : is_string X
IsT : host_is_tm A *
IsT1 : host_is_tm B *
H1 : subst X R A S
============================
 exists S, subst X R (plus A B) S
 < apply IH to IsT1 IsX with
     R = R.

Subgoal 5:

Variables: X R B A S S1
IH : forall X R T, host_is_tm T * -> is_string X -> exists S, subst X R T S
IsX : is_string X
IsT : host_is_tm A *
IsT1 : host_is_tm B *
H1 : subst X R A S
H2 : subst X R B S1
============================
 exists S, subst X R (plus A B) S
 < 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
 < case V.

Subgoal 1:

Variables: T Ty X
Ty : typeOf [] (abs X Ty T) intTy
============================
 exists I, abs X Ty T = num I
 < case Ty.

Subgoal 2:

Variables: 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
 < case V.

Subgoal 1:

Variables: Ty1 Ty2 T Ty X
Ty : typeOf [] (abs X Ty T) (arrowTy Ty1 Ty2)
============================
 exists X1 B, abs X Ty T = abs X1 Ty1 B
 < case Ty.

Subgoal 1:

Variables: Ty1 Ty2 T X
H1 : typeOf [(X, Ty1)] T Ty2
============================
 exists X1 B, abs X Ty1 T = abs X1 Ty1 B
 < search.

Subgoal 2:

Variables: Ty1 Ty2 I
Ty : typeOf [] (num I) (arrowTy Ty1 Ty2)
============================
 exists X B, num I = abs X Ty1 B
 < case Ty.

Proof completed.
 < Theorem progress :
     forall T Ty,
       host_is_tm T -> typeOf [] T Ty -> (exists T', eval T T') \/ value T.

============================
 forall T Ty,
   host_is_tm T -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
 < induction on 1.

IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
============================
 forall T Ty,
   host_is_tm T @ -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
 < intros IsT Ty.

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

Subgoal 1:

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

Subgoal 1:

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

Subgoal 2:

Variables: Ty B Ty1 X
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
Ty : typeOf [] (abs X Ty1 B) Ty
IsT : is_string X
IsT1 : host_is_ty Ty1
IsT2 : host_is_tm B *
============================
 (exists T', eval (abs X Ty1 B) T') \/ value (abs X Ty1 B)
 < search.

Subgoal 3:

Variables: Ty B A
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
Ty : typeOf [] (app A B) Ty
IsT : host_is_tm A *
IsT1 : host_is_tm B *
============================
 (exists T', eval (app A B) T') \/ value (app A B)
 < Ty: case Ty.

Subgoal 3:

Variables: Ty B A Ty1
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
IsT : host_is_tm A *
IsT1 : host_is_tm B *
Ty : typeOf [] A (arrowTy Ty1 Ty)
Ty1 : typeOf [] B Ty1
============================
 (exists T', eval (app A B) T') \/ value (app A B)
 < Or1: apply IH to IsT Ty.

Subgoal 3:

Variables: Ty B A Ty1
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
IsT : host_is_tm A *
IsT1 : host_is_tm B *
Ty : typeOf [] A (arrowTy Ty1 Ty)
Ty1 : typeOf [] B Ty1
Or1 : (exists T', eval A T') \/ value A
============================
 (exists T', eval (app A B) T') \/ value (app A B)
 < Or2: apply IH to IsT1 Ty1.

Subgoal 3:

Variables: Ty B A Ty1
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
IsT : host_is_tm A *
IsT1 : host_is_tm B *
Ty : typeOf [] A (arrowTy Ty1 Ty)
Ty1 : typeOf [] B Ty1
Or1 : (exists T', eval A T') \/ value A
Or2 : (exists T', eval B T') \/ value B
============================
 (exists T', eval (app A B) T') \/ value (app A B)
 < Ev1: case Or1.

Subgoal 3.1:

Variables: Ty B A Ty1 T'
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
IsT : host_is_tm A *
IsT1 : host_is_tm B *
Ty : typeOf [] A (arrowTy Ty1 Ty)
Ty1 : typeOf [] B Ty1
Or2 : (exists T', eval B T') \/ value B
Ev1 : eval A T'
============================
 (exists T', eval (app A B) T') \/ value (app A B)
 < search.

Subgoal 3.2:

Variables: Ty B A Ty1
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
IsT : host_is_tm A *
IsT1 : host_is_tm B *
Ty : typeOf [] A (arrowTy Ty1 Ty)
Ty1 : typeOf [] B Ty1
Or2 : (exists T', eval B T') \/ value B
Ev1 : value A
============================
 (exists T', eval (app A B) T') \/ value (app A B)
 < Ev2: case Or2.

Subgoal 3.2.1:

Variables: Ty B A Ty1 T'
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
IsT : host_is_tm A *
IsT1 : host_is_tm B *
Ty : typeOf [] A (arrowTy Ty1 Ty)
Ty1 : typeOf [] B Ty1
Ev1 : value A
Ev2 : eval B T'
============================
 (exists T', eval (app A B) T') \/ value (app A B)
 < search.

Subgoal 3.2.2:

Variables: Ty B A Ty1
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
IsT : host_is_tm A *
IsT1 : host_is_tm B *
Ty : typeOf [] A (arrowTy Ty1 Ty)
Ty1 : typeOf [] B Ty1
Ev1 : value A
Ev2 : value B
============================
 (exists T', eval (app A B) T') \/ value (app A B)
 < apply canonical_form_arrowTy to _ Ty.

Subgoal 3.2.2:

Variables: Ty B Ty1 X B1
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
IsT : host_is_tm (abs X Ty1 B1) *
IsT1 : host_is_tm B *
Ty : typeOf [] (abs X Ty1 B1) (arrowTy Ty1 Ty)
Ty1 : typeOf [] B Ty1
Ev1 : value (abs X Ty1 B1)
Ev2 : value B
============================
 (exists T', eval (app (abs X Ty1 B1) B) T') \/ value (app (abs X Ty1 B1) B)
 < IsAbs: case IsT.

Subgoal 3.2.2:

Variables: Ty B Ty1 X B1
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
IsT1 : host_is_tm B *
Ty : typeOf [] (abs X Ty1 B1) (arrowTy Ty1 Ty)
Ty1 : typeOf [] B Ty1
Ev1 : value (abs X Ty1 B1)
Ev2 : value B
IsAbs : is_string X
IsAbs1 : host_is_ty Ty1
IsAbs2 : host_is_tm B1 *
============================
 (exists T', eval (app (abs X Ty1 B1) B) T') \/ value (app (abs X Ty1 B1) B)
 < apply subst_total to IsAbs2 IsAbs with
     R = B.

Subgoal 3.2.2:

Variables: Ty B Ty1 X B1 S
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
IsT1 : host_is_tm B *
Ty : typeOf [] (abs X Ty1 B1) (arrowTy Ty1 Ty)
Ty1 : typeOf [] B Ty1
Ev1 : value (abs X Ty1 B1)
Ev2 : value B
IsAbs : is_string X
IsAbs1 : host_is_ty Ty1
IsAbs2 : host_is_tm B1 *
H1 : subst X B B1 S
============================
 (exists T', eval (app (abs X Ty1 B1) B) T') \/ value (app (abs X Ty1 B1) B)
 < search.

Subgoal 4:

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

Subgoal 5:

Variables: Ty B A
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
Ty : typeOf [] (plus A B) Ty
IsT : host_is_tm A *
IsT1 : host_is_tm B *
============================
 (exists T', eval (plus A B) T') \/ value (plus A B)
 < Ty: case Ty.

Subgoal 5:

Variables: B A
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
IsT : host_is_tm A *
IsT1 : host_is_tm B *
Ty : typeOf [] A intTy
Ty1 : typeOf [] B intTy
============================
 (exists T', eval (plus A B) T') \/ value (plus A B)
 < Or1: apply IH to IsT Ty.

Subgoal 5:

Variables: B A
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
IsT : host_is_tm A *
IsT1 : host_is_tm B *
Ty : typeOf [] A intTy
Ty1 : typeOf [] B intTy
Or1 : (exists T', eval A T') \/ value A
============================
 (exists T', eval (plus A B) T') \/ value (plus A B)
 < Or2: apply IH to IsT1 Ty1.

Subgoal 5:

Variables: B A
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
IsT : host_is_tm A *
IsT1 : host_is_tm B *
Ty : typeOf [] A intTy
Ty1 : typeOf [] B intTy
Or1 : (exists T', eval A T') \/ value A
Or2 : (exists T', eval B T') \/ value B
============================
 (exists T', eval (plus A B) T') \/ value (plus A B)
 < Ev1: case Or1.

Subgoal 5.1:

Variables: B A T'
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
IsT : host_is_tm A *
IsT1 : host_is_tm B *
Ty : typeOf [] A intTy
Ty1 : typeOf [] B intTy
Or2 : (exists T', eval B T') \/ value B
Ev1 : eval A T'
============================
 (exists T', eval (plus A B) T') \/ value (plus A B)
 < search.

Subgoal 5.2:

Variables: B A
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
IsT : host_is_tm A *
IsT1 : host_is_tm B *
Ty : typeOf [] A intTy
Ty1 : typeOf [] B intTy
Or2 : (exists T', eval B T') \/ value B
Ev1 : value A
============================
 (exists T', eval (plus A B) T') \/ value (plus A B)
 < Ev2: case Or2.

Subgoal 5.2.1:

Variables: B A T'
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
IsT : host_is_tm A *
IsT1 : host_is_tm B *
Ty : typeOf [] A intTy
Ty1 : typeOf [] B intTy
Ev1 : value A
Ev2 : eval B T'
============================
 (exists T', eval (plus A B) T') \/ value (plus A B)
 < search.

Subgoal 5.2.2:

Variables: B A
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
IsT : host_is_tm A *
IsT1 : host_is_tm B *
Ty : typeOf [] A intTy
Ty1 : typeOf [] B intTy
Ev1 : value A
Ev2 : value B
============================
 (exists T', eval (plus A B) T') \/ value (plus A B)
 < apply canonical_form_intTy to _ Ty.

Subgoal 5.2.2:

Variables: B I
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
IsT : host_is_tm (num I) *
IsT1 : host_is_tm B *
Ty : typeOf [] (num I) intTy
Ty1 : typeOf [] B intTy
Ev1 : value (num I)
Ev2 : value B
============================
 (exists T', eval (plus (num I) B) T') \/ value (plus (num I) B)
 < Is1: case IsT.

Subgoal 5.2.2:

Variables: B I
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
IsT1 : host_is_tm B *
Ty : typeOf [] (num I) intTy
Ty1 : typeOf [] B intTy
Ev1 : value (num I)
Ev2 : value B
Is1 : is_integer I
============================
 (exists T', eval (plus (num I) B) T') \/ value (plus (num I) B)
 < apply canonical_form_intTy to _ Ty1.

Subgoal 5.2.2:

Variables: I I1
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
IsT1 : host_is_tm (num I1) *
Ty : typeOf [] (num I) intTy
Ty1 : typeOf [] (num I1) intTy
Ev1 : value (num I)
Ev2 : value (num I1)
Is1 : is_integer I
============================
 (exists T', eval (plus (num I) (num I1)) T') \/ value (plus (num I) (num I1))
 < Is2: case IsT1.

Subgoal 5.2.2:

Variables: I I1
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
Ty : typeOf [] (num I) intTy
Ty1 : typeOf [] (num I1) intTy
Ev1 : value (num I)
Ev2 : value (num I1)
Is1 : is_integer I
Is2 : is_integer I1
============================
 (exists T', eval (plus (num I) (num I1)) T') \/ value (plus (num I) (num I1))
 < apply plus_integer_total to Is1 Is2.

Subgoal 5.2.2:

Variables: I I1 N3
IH : forall T Ty,
       host_is_tm T * -> typeOf [] T Ty -> (exists T', eval T T') \/ value T
Ty : typeOf [] (num I) intTy
Ty1 : typeOf [] (num I1) intTy
Ev1 : value (num I)
Ev2 : value (num I1)
Is1 : is_integer I
Is2 : 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