Reasoning Details

 < Module mtc:lambda.
 < Theorem typeOfCtx_lookups :
     forall TG EG X Ty V,
       typeOfCtx TG EG -> lookup TG X Ty -> lookup EG X V -> valueType V Ty.

============================
 forall TG EG X Ty V,
   typeOfCtx TG EG -> lookup TG X Ty -> lookup EG X V -> valueType V Ty
 < induction on 2.

IH : forall TG EG X Ty V,
       typeOfCtx TG EG -> lookup TG X Ty * -> lookup EG X V -> valueType V Ty
============================
 forall TG EG X Ty V,
   typeOfCtx TG EG -> lookup TG X Ty @ -> lookup EG X V -> valueType V Ty
 < intros TOC LT LV.

Variables: TG EG X Ty V
IH : forall TG EG X Ty V,
       typeOfCtx TG EG -> lookup TG X Ty * -> lookup EG X V -> valueType V Ty
TOC : typeOfCtx TG EG
LT : lookup TG X Ty @
LV : lookup EG X V
============================
 valueType V Ty
 < LT: case LT.

Subgoal 1:

Variables: EG X Ty V Rest
IH : forall TG EG X Ty V,
       typeOfCtx TG EG -> lookup TG X Ty * -> lookup EG X V -> valueType V Ty
TOC : typeOfCtx ((X, Ty)::Rest) EG
LV : lookup EG X V
============================
 valueType V Ty
 < LV: case LV.

Subgoal 1.1:

Variables: X Ty V Rest Rest1
IH : forall TG EG X Ty V,
       typeOfCtx TG EG -> lookup TG X Ty * -> lookup EG X V -> valueType V Ty
TOC : typeOfCtx ((X, Ty)::Rest) ((X, V)::Rest1)
============================
 valueType V Ty
 < case TOC.

Subgoal 1.1:

Variables: X Ty V Rest Rest1
IH : forall TG EG X Ty V,
       typeOfCtx TG EG -> lookup TG X Ty * -> lookup EG X V -> valueType V Ty
H1 : valueType V Ty
H2 : typeOfCtx Rest Rest1
============================
 valueType V Ty
 < search.

Subgoal 1.2:

Variables: X Ty V Rest Rest1 V1 K
IH : forall TG EG X Ty V,
       typeOfCtx TG EG -> lookup TG X Ty * -> lookup EG X V -> valueType V Ty
TOC : typeOfCtx ((X, Ty)::Rest) ((K, V1)::Rest1)
LV : K = X -> false
LV1 : lookup Rest1 X V
============================
 valueType V Ty
 < case TOC.

Subgoal 1.2:

Variables: Ty V Rest Rest1 V1 K
IH : forall TG EG X Ty V,
       typeOfCtx TG EG -> lookup TG X Ty * -> lookup EG X V -> valueType V Ty
LV : K = K -> false
LV1 : lookup Rest1 K V
H1 : valueType V1 Ty
H2 : typeOfCtx Rest Rest1
============================
 valueType V Ty
 < apply LV to _.

Subgoal 2:

Variables: EG X Ty V Rest V1 K
IH : forall TG EG X Ty V,
       typeOfCtx TG EG -> lookup TG X Ty * -> lookup EG X V -> valueType V Ty
TOC : typeOfCtx ((K, V1)::Rest) EG
LV : lookup EG X V
LT : K = X -> false
LT1 : lookup Rest X Ty *
============================
 valueType V Ty
 < LV: case LV.

Subgoal 2.1:

Variables: X Ty V Rest V1 K Rest1
IH : forall TG EG X Ty V,
       typeOfCtx TG EG -> lookup TG X Ty * -> lookup EG X V -> valueType V Ty
TOC : typeOfCtx ((K, V1)::Rest) ((X, V)::Rest1)
LT : K = X -> false
LT1 : lookup Rest X Ty *
============================
 valueType V Ty
 < case TOC.

Subgoal 2.1:

Variables: X Ty V Rest V1 Rest1
IH : forall TG EG X Ty V,
       typeOfCtx TG EG -> lookup TG X Ty * -> lookup EG X V -> valueType V Ty
LT : X = X -> false
LT1 : lookup Rest X Ty *
H1 : valueType V V1
H2 : typeOfCtx Rest Rest1
============================
 valueType V Ty
 < apply LT to _.

Subgoal 2.2:

Variables: X Ty V Rest V1 K Rest1 V2 K1
IH : forall TG EG X Ty V,
       typeOfCtx TG EG -> lookup TG X Ty * -> lookup EG X V -> valueType V Ty
TOC : typeOfCtx ((K, V1)::Rest) ((K1, V2)::Rest1)
LT : K = X -> false
LT1 : lookup Rest X Ty *
LV : K1 = X -> false
LV1 : lookup Rest1 X V
============================
 valueType V Ty
 < TOC: case TOC.

Subgoal 2.2:

Variables: X Ty V Rest V1 Rest1 V2 K1
IH : forall TG EG X Ty V,
       typeOfCtx TG EG -> lookup TG X Ty * -> lookup EG X V -> valueType V Ty
LT : K1 = X -> false
LT1 : lookup Rest X Ty *
LV : K1 = X -> false
LV1 : lookup Rest1 X V
TOC : valueType V2 V1
TOC1 : typeOfCtx Rest Rest1
============================
 valueType V Ty
 < apply IH to _ LT1 LV1.

Subgoal 2.2:

Variables: X Ty V Rest V1 Rest1 V2 K1
IH : forall TG EG X Ty V,
       typeOfCtx TG EG -> lookup TG X Ty * -> lookup EG X V -> valueType V Ty
LT : K1 = X -> false
LT1 : lookup Rest X Ty *
LV : K1 = X -> false
LV1 : lookup Rest1 X V
TOC : valueType V2 V1
TOC1 : typeOfCtx Rest Rest1
H1 : valueType V Ty
============================
 valueType V Ty
 < search.

Proof completed.
 < Prove mtc:shared_declarations:type_preservation.

Subgoal 1:

Variables: TG Ty EG E1 X Ty1
IH : forall TG E Ty EG V,
       typeOfCtx TG EG -> typeOf TG E Ty -> eval EG E V * -> valueType V Ty
Rel : typeOfCtx TG EG
Ty : typeOf TG (abs X Ty1 E1) Ty
Ev : eval EG (abs X Ty1 E1) (closure EG X E1) @
============================
 valueType (closure EG X E1) Ty
 < case Ty.

Subgoal 1:

Variables: TG EG E1 X Ty1 Ty3
IH : forall TG E Ty EG V,
       typeOfCtx TG EG -> typeOf TG E Ty -> eval EG E V * -> valueType V Ty
Rel : typeOfCtx TG EG
Ev : eval EG (abs X Ty1 E1) (closure EG X E1) @
H1 : typeOf ((X, Ty1)::TG) E1 Ty3
============================
 valueType (closure EG X E1) (arrowTy Ty1 Ty3)
 < search.

Subgoal 2:

Variables: TG Ty EG V GC X Body V2 E2 E1
IH : forall TG E Ty EG V,
       typeOfCtx TG EG -> typeOf TG E Ty -> eval EG E V * -> valueType V Ty
Rel : typeOfCtx TG EG
Ty : typeOf TG (app E1 E2) Ty
Ev : eval EG (app E1 E2) V @
Ev1 : eval EG E1 (closure GC X Body) *
Ev2 : eval EG E2 V2 *
Ev3 : eval ((X, V2)::GC) Body V *
============================
 valueType V Ty
 < Ty: case Ty.

Subgoal 2:

Variables: TG Ty EG V GC X Body V2 E2 E1 Ty1
IH : forall TG E Ty EG V,
       typeOfCtx TG EG -> typeOf TG E Ty -> eval EG E V * -> valueType V Ty
Rel : typeOfCtx TG EG
Ev : eval EG (app E1 E2) V @
Ev1 : eval EG E1 (closure GC X Body) *
Ev2 : eval EG E2 V2 *
Ev3 : eval ((X, V2)::GC) Body V *
Ty : typeOf TG E1 (arrowTy Ty1 Ty)
Ty1 : typeOf TG E2 Ty1
============================
 valueType V Ty
 < VT1: apply IH to _ Ty Ev1.

Subgoal 2:

Variables: TG Ty EG V GC X Body V2 E2 E1 Ty1
IH : forall TG E Ty EG V,
       typeOfCtx TG EG -> typeOf TG E Ty -> eval EG E V * -> valueType V Ty
Rel : typeOfCtx TG EG
Ev : eval EG (app E1 E2) V @
Ev1 : eval EG E1 (closure GC X Body) *
Ev2 : eval EG E2 V2 *
Ev3 : eval ((X, V2)::GC) Body V *
Ty : typeOf TG E1 (arrowTy Ty1 Ty)
Ty1 : typeOf TG E2 Ty1
VT1 : valueType (closure GC X Body) (arrowTy Ty1 Ty)
============================
 valueType V Ty
 < VT2: apply IH to _ Ty1 Ev2.

Subgoal 2:

Variables: TG Ty EG V GC X Body V2 E2 E1 Ty1
IH : forall TG E Ty EG V,
       typeOfCtx TG EG -> typeOf TG E Ty -> eval EG E V * -> valueType V Ty
Rel : typeOfCtx TG EG
Ev : eval EG (app E1 E2) V @
Ev1 : eval EG E1 (closure GC X Body) *
Ev2 : eval EG E2 V2 *
Ev3 : eval ((X, V2)::GC) Body V *
Ty : typeOf TG E1 (arrowTy Ty1 Ty)
Ty1 : typeOf TG E2 Ty1
VT1 : valueType (closure GC X Body) (arrowTy Ty1 Ty)
VT2 : valueType V2 Ty1
============================
 valueType V Ty
 < VTC: case VT1.

Subgoal 2:

Variables: TG Ty EG V GC X Body V2 E2 E1 Ty1 TG1
IH : forall TG E Ty EG V,
       typeOfCtx TG EG -> typeOf TG E Ty -> eval EG E V * -> valueType V Ty
Rel : typeOfCtx TG EG
Ev : eval EG (app E1 E2) V @
Ev1 : eval EG E1 (closure GC X Body) *
Ev2 : eval EG E2 V2 *
Ev3 : eval ((X, V2)::GC) Body V *
Ty : typeOf TG E1 (arrowTy Ty1 Ty)
Ty1 : typeOf TG E2 Ty1
VT2 : valueType V2 Ty1
VTC : typeOfCtx TG1 GC
VTC1 : typeOf ((X, Ty1)::TG1) Body Ty
============================
 valueType V Ty
 < apply IH to _ VTC1 Ev3.

Subgoal 2:

Variables: TG Ty EG V GC X Body V2 E2 E1 Ty1 TG1
IH : forall TG E Ty EG V,
       typeOfCtx TG EG -> typeOf TG E Ty -> eval EG E V * -> valueType V Ty
Rel : typeOfCtx TG EG
Ev : eval EG (app E1 E2) V @
Ev1 : eval EG E1 (closure GC X Body) *
Ev2 : eval EG E2 V2 *
Ev3 : eval ((X, V2)::GC) Body V *
Ty : typeOf TG E1 (arrowTy Ty1 Ty)
Ty1 : typeOf TG E2 Ty1
VT2 : valueType V2 Ty1
VTC : typeOfCtx TG1 GC
VTC1 : typeOf ((X, Ty1)::TG1) Body Ty
H1 : valueType V Ty
============================
 valueType V Ty
 < search.

Subgoal 3:

Variables: TG Ty EG V X
IH : forall TG E Ty EG V,
       typeOfCtx TG EG -> typeOf TG E Ty -> eval EG E V * -> valueType V Ty
Rel : typeOfCtx TG EG
Ty : typeOf TG (var X) Ty
Ev : eval EG (var X) V @
Ev1 : lookup EG X V
============================
 valueType V Ty
 < Ty: case Ty.

Subgoal 3:

Variables: TG Ty EG V X
IH : forall TG E Ty EG V,
       typeOfCtx TG EG -> typeOf TG E Ty -> eval EG E V * -> valueType V Ty
Rel : typeOfCtx TG EG
Ev : eval EG (var X) V @
Ev1 : lookup EG X V
Ty : lookup TG X Ty
============================
 valueType V Ty
 < apply typeOfCtx_lookups to _ Ty Ev1.

Subgoal 3:

Variables: TG Ty EG V X
IH : forall TG E Ty EG V,
       typeOfCtx TG EG -> typeOf TG E Ty -> eval EG E V * -> valueType V Ty
Rel : typeOfCtx TG EG
Ev : eval EG (var X) V @
Ev1 : lookup EG X V
Ty : lookup TG X Ty
H1 : valueType V Ty
============================
 valueType V Ty
 < search.

Proof completed.
 < Prove mtc:shared_declarations:value_evalStep_false.

Subgoal 1:

Variables: E' E1 Ty X
IH : forall E E', value E * -> evalStep E E' -> false
V : value (abs X Ty E1) @
Ev : evalStep (abs X Ty E1) E'
============================
 false
 < case Ev.

Proof completed.
 < Prove mtc:shared_declarations:subst_unique.

Subgoal 1:

Variables: X R EB E1 Ty
IH : forall X R E EA EB, subst X R E EA * -> subst X R E EB -> EA = EB
SA : subst X R (abs X Ty E1) (abs X Ty E1) @
SB : subst X R (abs X Ty E1) EB
============================
 abs X Ty E1 = EB
 < SB: case SB.

Subgoal 1.1:

Variables: X R E1 Ty
IH : forall X R E EA EB, subst X R E EA * -> subst X R E EB -> EA = EB
SA : subst X R (abs X Ty E1) (abs X Ty E1) @
============================
 abs X Ty E1 = abs X Ty E1
 < search.

Subgoal 1.2:

Variables: X R E1 Ty E3
IH : forall X R E EA EB, subst X R E EA * -> subst X R E EB -> EA = EB
SA : subst X R (abs X Ty E1) (abs X Ty E1) @
SB : X = X -> false
SB1 : subst X R E1 E3
============================
 abs X Ty E1 = abs X Ty E3
 < apply SB to _.

Subgoal 2:

Variables: X R EB E2 Ty Y E1
IH : forall X R E EA EB, subst X R E EA * -> subst X R E EB -> EA = EB
SA : subst X R (abs Y Ty E1) (abs Y Ty E2) @
SB : subst X R (abs Y Ty E1) EB
SA1 : X = Y -> false
SA2 : subst X R E1 E2 *
============================
 abs Y Ty E2 = EB
 < SB: case SB.

Subgoal 2.1:

Variables: R E2 Ty Y E1
IH : forall X R E EA EB, subst X R E EA * -> subst X R E EB -> EA = EB
SA : subst Y R (abs Y Ty E1) (abs Y Ty E2) @
SA1 : Y = Y -> false
SA2 : subst Y R E1 E2 *
============================
 abs Y Ty E2 = abs Y Ty E1
 < apply SA1 to _.

Subgoal 2.2:

Variables: X R E2 Ty Y E1 E4
IH : forall X R E EA EB, subst X R E EA * -> subst X R E EB -> EA = EB
SA : subst X R (abs Y Ty E1) (abs Y Ty E2) @
SA1 : X = Y -> false
SA2 : subst X R E1 E2 *
SB : X = Y -> false
SB1 : subst X R E1 E4
============================
 abs Y Ty E2 = abs Y Ty E4
 < apply IH to SA2 SB1.

Subgoal 2.2:

Variables: X R Ty Y E1 E4
IH : forall X R E EA EB, subst X R E EA * -> subst X R E EB -> EA = EB
SA : subst X R (abs Y Ty E1) (abs Y Ty E4) @
SA1 : X = Y -> false
SA2 : subst X R E1 E4 *
SB : X = Y -> false
SB1 : subst X R E1 E4
============================
 abs Y Ty E4 = abs Y Ty E4
 < search.

Subgoal 3:

Variables: X R EB E21 E11 E2 E1
IH : forall X R E EA EB, subst X R E EA * -> subst X R E EB -> EA = EB
SA : subst X R (app E1 E2) (app E11 E21) @
SB : subst X R (app E1 E2) EB
SA1 : subst X R E1 E11 *
SA2 : subst X R E2 E21 *
============================
 app E11 E21 = EB
 < SB: case SB.

Subgoal 3:

Variables: X R E21 E11 E2 E1 E6 E5
IH : forall X R E EA EB, subst X R E EA * -> subst X R E EB -> EA = EB
SA : subst X R (app E1 E2) (app E11 E21) @
SA1 : subst X R E1 E11 *
SA2 : subst X R E2 E21 *
SB : subst X R E1 E5
SB1 : subst X R E2 E6
============================
 app E11 E21 = app E5 E6
 < apply IH to SA1 SB.

Subgoal 3:

Variables: X R E21 E2 E1 E6 E5
IH : forall X R E EA EB, subst X R E EA * -> subst X R E EB -> EA = EB
SA : subst X R (app E1 E2) (app E5 E21) @
SA1 : subst X R E1 E5 *
SA2 : subst X R E2 E21 *
SB : subst X R E1 E5
SB1 : subst X R E2 E6
============================
 app E5 E21 = app E5 E6
 < apply IH to SA2 SB1.

Subgoal 3:

Variables: X R E2 E1 E6 E5
IH : forall X R E EA EB, subst X R E EA * -> subst X R E EB -> EA = EB
SA : subst X R (app E1 E2) (app E5 E6) @
SA1 : subst X R E1 E5 *
SA2 : subst X R E2 E6 *
SB : subst X R E1 E5
SB1 : subst X R E2 E6
============================
 app E5 E6 = app E5 E6
 < search.

Subgoal 4:

Variables: X EA EB
IH : forall X R E EA EB, subst X R E EA * -> subst X R E EB -> EA = EB
SA : subst X EA (var X) EA @
SB : subst X EA (var X) EB
============================
 EA = EB
 < SB: case SB.

Subgoal 4.1:

Variables: X EB
IH : forall X R E EA EB, subst X R E EA * -> subst X R E EB -> EA = EB
SA : subst X EB (var X) EB @
============================
 EB = EB
 < search.

Subgoal 4.2:

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

Subgoal 5:

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

Subgoal 5.1:

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

Subgoal 5.2:

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

Proof completed.
 < Prove mtc:shared_declarations:evalStep_unique.

Subgoal 1:

Variables: EB E2 E11 E1
IH : forall E EA EB, evalStep E EA * -> evalStep E EB -> EA = EB
EvA : evalStep (app E1 E2) (app E11 E2) @
EvB : evalStep (app E1 E2) EB
EvA1 : evalStep E1 E11 *
============================
 app E11 E2 = EB
 < EvB: case EvB.

Subgoal 1.1:

Variables: E2 E11 E1 E5
IH : forall E EA EB, evalStep E EA * -> evalStep E EB -> EA = EB
EvA : evalStep (app E1 E2) (app E11 E2) @
EvA1 : evalStep E1 E11 *
EvB : evalStep E1 E5
============================
 app E11 E2 = app E5 E2
 < apply IH to EvA1 EvB.

Subgoal 1.1:

Variables: E2 E1 E5
IH : forall E EA EB, evalStep E EA * -> evalStep E EB -> EA = EB
EvA : evalStep (app E1 E2) (app E5 E2) @
EvA1 : evalStep E1 E5 *
EvB : evalStep E1 E5
============================
 app E5 E2 = app E5 E2
 < search.

Subgoal 1.2:

Variables: E2 E11 E1 E21
IH : forall E EA EB, evalStep E EA * -> evalStep E EB -> EA = EB
EvA : evalStep (app E1 E2) (app E11 E2) @
EvA1 : evalStep E1 E11 *
EvB : value E1
EvB1 : evalStep E2 E21
============================
 app E11 E2 = app E1 E21
 < apply value_evalStep_false to EvB EvA1.

Subgoal 1.3:

Variables: EB E2 E11 E3 Ty X
IH : forall E EA EB, evalStep E EA * -> evalStep E EB -> EA = EB
EvA : evalStep (app (abs X Ty E3) E2) (app E11 E2) @
EvA1 : evalStep (abs X Ty E3) E11 *
EvB : value E2
EvB1 : subst X E2 E3 EB
============================
 app E11 E2 = EB
 < case EvA1.

Subgoal 2:

Variables: EB E21 E1 E2
IH : forall E EA EB, evalStep E EA * -> evalStep E EB -> EA = EB
EvA : evalStep (app E1 E2) (app E1 E21) @
EvB : evalStep (app E1 E2) EB
EvA1 : value E1
EvA2 : evalStep E2 E21 *
============================
 app E1 E21 = EB
 < EvB: case EvB.

Subgoal 2.1:

Variables: E21 E1 E2 E11
IH : forall E EA EB, evalStep E EA * -> evalStep E EB -> EA = EB
EvA : evalStep (app E1 E2) (app E1 E21) @
EvA1 : value E1
EvA2 : evalStep E2 E21 *
EvB : evalStep E1 E11
============================
 app E1 E21 = app E11 E2
 < apply value_evalStep_false to EvA1 EvB.

Subgoal 2.2:

Variables: E21 E1 E2 E5
IH : forall E EA EB, evalStep E EA * -> evalStep E EB -> EA = EB
EvA : evalStep (app E1 E2) (app E1 E21) @
EvA1 : value E1
EvA2 : evalStep E2 E21 *
EvB : value E1
EvB1 : evalStep E2 E5
============================
 app E1 E21 = app E1 E5
 < apply IH to EvA2 EvB1.

Subgoal 2.2:

Variables: E1 E2 E5
IH : forall E EA EB, evalStep E EA * -> evalStep E EB -> EA = EB
EvA : evalStep (app E1 E2) (app E1 E5) @
EvA1 : value E1
EvA2 : evalStep E2 E5 *
EvB : value E1
EvB1 : evalStep E2 E5
============================
 app E1 E5 = app E1 E5
 < search.

Subgoal 2.3:

Variables: EB E21 E2 E3 Ty X
IH : forall E EA EB, evalStep E EA * -> evalStep E EB -> EA = EB
EvA : evalStep (app (abs X Ty E3) E2) (app (abs X Ty E3) E21) @
EvA1 : value (abs X Ty E3)
EvA2 : evalStep E2 E21 *
EvB : value E2
EvB1 : subst X E2 E3 EB
============================
 app (abs X Ty E3) E21 = EB
 < apply value_evalStep_false to EvB EvA2.

Subgoal 3:

Variables: EA EB E2 E1 Ty X
IH : forall E EA EB, evalStep E EA * -> evalStep E EB -> EA = EB
EvA : evalStep (app (abs X Ty E1) E2) EA @
EvB : evalStep (app (abs X Ty E1) E2) EB
EvA1 : value E2
EvA2 : subst X E2 E1 EA
============================
 EA = EB
 < EvB: case EvB.

Subgoal 3.1:

Variables: EA E2 E1 Ty X E11
IH : forall E EA EB, evalStep E EA * -> evalStep E EB -> EA = EB
EvA : evalStep (app (abs X Ty E1) E2) EA @
EvA1 : value E2
EvA2 : subst X E2 E1 EA
EvB : evalStep (abs X Ty E1) E11
============================
 EA = app E11 E2
 < case EvB.

Subgoal 3.2:

Variables: EA E2 E1 Ty X E21
IH : forall E EA EB, evalStep E EA * -> evalStep E EB -> EA = EB
EvA : evalStep (app (abs X Ty E1) E2) EA @
EvA1 : value E2
EvA2 : subst X E2 E1 EA
EvB : value (abs X Ty E1)
EvB1 : evalStep E2 E21
============================
 EA = app (abs X Ty E1) E21
 < apply value_evalStep_false to EvA1 EvB1.

Subgoal 3.3:

Variables: EA EB E2 E1 Ty X
IH : forall E EA EB, evalStep E EA * -> evalStep E EB -> EA = EB
EvA : evalStep (app (abs X Ty E1) E2) EA @
EvA1 : value E2
EvA2 : subst X E2 E1 EA
EvB : value E2
EvB1 : subst X E2 E1 EB
============================
 EA = EB
 < apply subst_unique to EvA2 EvB1.

Subgoal 3.3:

Variables: EB E2 E1 Ty X
IH : forall E EA EB, evalStep E EA * -> evalStep E EB -> EA = EB
EvA : evalStep (app (abs X Ty E1) E2) EB @
EvA1 : value E2
EvA2 : subst X E2 E1 EB
EvB : value E2
EvB1 : subst X E2 E1 EB
============================
 EB = EB
 < search.

Proof completed.
 < Prove mtc:shared_declarations:ty_lookup.

Subgoal 1:

Variables: G1 G2 Ty2 Ty1 E1 X
IH : forall G1 G2 E Ty,
       typeOf G1 E Ty * -> (forall X XTy, lookup G1 X XTy -> lookup G2 X XTy) ->
       typeOf G2 E Ty
Ty : typeOf G1 (abs X Ty1 E1) (arrowTy Ty1 Ty2) @
L : forall X XTy, lookup G1 X XTy -> lookup G2 X XTy
Ty1 : typeOf ((X, Ty1)::G1) E1 Ty2 *
============================
 typeOf G2 (abs X Ty1 E1) (arrowTy Ty1 Ty2)
 < apply IH to Ty1 _ with
     G2 = (X, Ty1)::G2.

Subgoal 1.1:

Variables: G1 G2 Ty2 Ty1 E1 X
IH : forall G1 G2 E Ty,
       typeOf G1 E Ty * -> (forall X XTy, lookup G1 X XTy -> lookup G2 X XTy) ->
       typeOf G2 E Ty
Ty : typeOf G1 (abs X Ty1 E1) (arrowTy Ty1 Ty2) @
L : forall X XTy, lookup G1 X XTy -> lookup G2 X XTy
Ty1 : typeOf ((X, Ty1)::G1) E1 Ty2 *
============================
 forall X1 XTy, lookup ((X, Ty1)::G1) X1 XTy -> lookup ((X, Ty1)::G2) X1 XTy
 < intros L'.

Subgoal 1.1:

Variables: G1 G2 Ty2 Ty1 E1 X X1 XTy
IH : forall G1 G2 E Ty,
       typeOf G1 E Ty * -> (forall X XTy, lookup G1 X XTy -> lookup G2 X XTy) ->
       typeOf G2 E Ty
Ty : typeOf G1 (abs X Ty1 E1) (arrowTy Ty1 Ty2) @
L : forall X XTy, lookup G1 X XTy -> lookup G2 X XTy
Ty1 : typeOf ((X, Ty1)::G1) E1 Ty2 *
L' : lookup ((X, Ty1)::G1) X1 XTy
============================
 lookup ((X, Ty1)::G2) X1 XTy
 < L': case L'.

Subgoal 1.1.1:

Variables: G1 G2 Ty2 E1 X1 XTy
IH : forall G1 G2 E Ty,
       typeOf G1 E Ty * -> (forall X XTy, lookup G1 X XTy -> lookup G2 X XTy) ->
       typeOf G2 E Ty
Ty : typeOf G1 (abs X1 XTy E1) (arrowTy XTy Ty2) @
L : forall X XTy, lookup G1 X XTy -> lookup G2 X XTy
Ty1 : typeOf ((X1, XTy)::G1) E1 Ty2 *
============================
 lookup ((X1, XTy)::G2) X1 XTy
 < search.

Subgoal 1.1.2:

Variables: G1 G2 Ty2 Ty1 E1 X X1 XTy
IH : forall G1 G2 E Ty,
       typeOf G1 E Ty * -> (forall X XTy, lookup G1 X XTy -> lookup G2 X XTy) ->
       typeOf G2 E Ty
Ty : typeOf G1 (abs X Ty1 E1) (arrowTy Ty1 Ty2) @
L : forall X XTy, lookup G1 X XTy -> lookup G2 X XTy
Ty1 : typeOf ((X, Ty1)::G1) E1 Ty2 *
L' : X = X1 -> false
L'1 : lookup G1 X1 XTy
============================
 lookup ((X, Ty1)::G2) X1 XTy
 < apply L to L'1.

Subgoal 1.1.2:

Variables: G1 G2 Ty2 Ty1 E1 X X1 XTy
IH : forall G1 G2 E Ty,
       typeOf G1 E Ty * -> (forall X XTy, lookup G1 X XTy -> lookup G2 X XTy) ->
       typeOf G2 E Ty
Ty : typeOf G1 (abs X Ty1 E1) (arrowTy Ty1 Ty2) @
L : forall X XTy, lookup G1 X XTy -> lookup G2 X XTy
Ty1 : typeOf ((X, Ty1)::G1) E1 Ty2 *
L' : X = X1 -> false
L'1 : lookup G1 X1 XTy
H1 : lookup G2 X1 XTy
============================
 lookup ((X, Ty1)::G2) X1 XTy
 < search.

Subgoal 1:

Variables: G1 G2 Ty2 Ty1 E1 X
IH : forall G1 G2 E Ty,
       typeOf G1 E Ty * -> (forall X XTy, lookup G1 X XTy -> lookup G2 X XTy) ->
       typeOf G2 E Ty
Ty : typeOf G1 (abs X Ty1 E1) (arrowTy Ty1 Ty2) @
L : forall X XTy, lookup G1 X XTy -> lookup G2 X XTy
Ty1 : typeOf ((X, Ty1)::G1) E1 Ty2 *
H1 : typeOf ((X, Ty1)::G2) E1 Ty2
============================
 typeOf G2 (abs X Ty1 E1) (arrowTy Ty1 Ty2)
 < search.

Subgoal 2:

Variables: G1 G2 Ty Ty1 E2 E1
IH : forall G1 G2 E Ty,
       typeOf G1 E Ty * -> (forall X XTy, lookup G1 X XTy -> lookup G2 X XTy) ->
       typeOf G2 E Ty
Ty : typeOf G1 (app E1 E2) Ty @
L : forall X XTy, lookup G1 X XTy -> lookup G2 X XTy
Ty1 : typeOf G1 E1 (arrowTy Ty1 Ty) *
Ty2 : typeOf G1 E2 Ty1 *
============================
 typeOf G2 (app E1 E2) Ty
 < apply IH to Ty1 L.

Subgoal 2:

Variables: G1 G2 Ty Ty1 E2 E1
IH : forall G1 G2 E Ty,
       typeOf G1 E Ty * -> (forall X XTy, lookup G1 X XTy -> lookup G2 X XTy) ->
       typeOf G2 E Ty
Ty : typeOf G1 (app E1 E2) Ty @
L : forall X XTy, lookup G1 X XTy -> lookup G2 X XTy
Ty1 : typeOf G1 E1 (arrowTy Ty1 Ty) *
Ty2 : typeOf G1 E2 Ty1 *
H1 : typeOf G2 E1 (arrowTy Ty1 Ty)
============================
 typeOf G2 (app E1 E2) Ty
 < apply IH to Ty2 L.

Subgoal 2:

Variables: G1 G2 Ty Ty1 E2 E1
IH : forall G1 G2 E Ty,
       typeOf G1 E Ty * -> (forall X XTy, lookup G1 X XTy -> lookup G2 X XTy) ->
       typeOf G2 E Ty
Ty : typeOf G1 (app E1 E2) Ty @
L : forall X XTy, lookup G1 X XTy -> lookup G2 X XTy
Ty1 : typeOf G1 E1 (arrowTy Ty1 Ty) *
Ty2 : typeOf G1 E2 Ty1 *
H1 : typeOf G2 E1 (arrowTy Ty1 Ty)
H2 : typeOf G2 E2 Ty1
============================
 typeOf G2 (app E1 E2) Ty
 < search.

Subgoal 3:

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

Subgoal 3:

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

Proof completed.
 < Prove mtc:shared_declarations:subst_preservation.

Subgoal 1:

Variables: X XTy TG Ty R E1 Ty1
IH : forall X XTy TG E Ty R E',
       typeOf ((X, XTy)::TG) E Ty -> subst X R E E' * -> typeOf [] R XTy -> typeOf TG E' Ty
Ty : typeOf ((X, XTy)::TG) (abs X Ty1 E1) Ty
S : subst X R (abs X Ty1 E1) (abs X Ty1 E1) @
RTy : typeOf [] R XTy
============================
 typeOf TG (abs X Ty1 E1) Ty
 < Ty: case Ty.

Subgoal 1:

Variables: X XTy TG R E1 Ty1 Ty3
IH : forall X XTy TG E Ty R E',
       typeOf ((X, XTy)::TG) E Ty -> subst X R E E' * -> typeOf [] R XTy -> typeOf TG E' Ty
S : subst X R (abs X Ty1 E1) (abs X Ty1 E1) @
RTy : typeOf [] R XTy
Ty : typeOf ((X, Ty1)::((X, XTy)::TG)) E1 Ty3
============================
 typeOf TG (abs X Ty1 E1) (arrowTy Ty1 Ty3)
 < apply ty_lookup to Ty _ with
     G2 = (X, Ty1)::TG.

Subgoal 1.1:

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

Subgoal 1.1:

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

Subgoal 1.1.1:

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

Subgoal 1.1.2:

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

Subgoal 1.1.2.1:

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

Subgoal 1.1.2.2:

Variables: X XTy TG R E1 Ty1 Ty3 X1 XTy1
IH : forall X XTy TG E Ty R E',
       typeOf ((X, XTy)::TG) E Ty -> subst X R E E' * -> typeOf [] R XTy -> typeOf TG E' Ty
S : subst X R (abs X Ty1 E1) (abs X Ty1 E1) @
RTy : typeOf [] R XTy
Ty : typeOf ((X, Ty1)::((X, XTy)::TG)) E1 Ty3
L : X = X1 -> false
L' : X = X1 -> false
L'1 : lookup TG X1 XTy1
============================
 lookup ((X, Ty1)::TG) X1 XTy1
 < search.

Subgoal 1:

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

Subgoal 2:

Variables: X XTy TG Ty R E2 Ty1 Y E1
IH : forall X XTy TG E Ty R E',
       typeOf ((X, XTy)::TG) E Ty -> subst X R E E' * -> typeOf [] R XTy -> typeOf TG E' Ty
Ty : typeOf ((X, XTy)::TG) (abs Y Ty1 E1) Ty
S : subst X R (abs Y Ty1 E1) (abs Y Ty1 E2) @
RTy : typeOf [] R XTy
S1 : X = Y -> false
S2 : subst X R E1 E2 *
============================
 typeOf TG (abs Y Ty1 E2) Ty
 < Ty: case Ty.

Subgoal 2:

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

Subgoal 2.1:

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

Subgoal 2.1:

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

Subgoal 2.1.1:

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

Subgoal 2.1.2:

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

Subgoal 2.1.2.1:

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

Subgoal 2.1.2.2:

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

Subgoal 2:

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

Subgoal 2:

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

Subgoal 3:

Variables: X XTy TG Ty R E21 E11 E2 E1
IH : forall X XTy TG E Ty R E',
       typeOf ((X, XTy)::TG) E Ty -> subst X R E E' * -> typeOf [] R XTy -> typeOf TG E' Ty
Ty : typeOf ((X, XTy)::TG) (app E1 E2) Ty
S : subst X R (app E1 E2) (app E11 E21) @
RTy : typeOf [] R XTy
S1 : subst X R E1 E11 *
S2 : subst X R E2 E21 *
============================
 typeOf TG (app E11 E21) Ty
 < Ty: case Ty.

Subgoal 3:

Variables: X XTy TG Ty R E21 E11 E2 E1 Ty1
IH : forall X XTy TG E Ty R E',
       typeOf ((X, XTy)::TG) E Ty -> subst X R E E' * -> typeOf [] R XTy -> typeOf TG E' Ty
S : subst X R (app E1 E2) (app E11 E21) @
RTy : typeOf [] R XTy
S1 : subst X R E1 E11 *
S2 : subst X R E2 E21 *
Ty : typeOf ((X, XTy)::TG) E1 (arrowTy Ty1 Ty)
Ty1 : typeOf ((X, XTy)::TG) E2 Ty1
============================
 typeOf TG (app E11 E21) Ty
 < apply IH to Ty S1 RTy.

Subgoal 3:

Variables: X XTy TG Ty R E21 E11 E2 E1 Ty1
IH : forall X XTy TG E Ty R E',
       typeOf ((X, XTy)::TG) E Ty -> subst X R E E' * -> typeOf [] R XTy -> typeOf TG E' Ty
S : subst X R (app E1 E2) (app E11 E21) @
RTy : typeOf [] R XTy
S1 : subst X R E1 E11 *
S2 : subst X R E2 E21 *
Ty : typeOf ((X, XTy)::TG) E1 (arrowTy Ty1 Ty)
Ty1 : typeOf ((X, XTy)::TG) E2 Ty1
H1 : typeOf TG E11 (arrowTy Ty1 Ty)
============================
 typeOf TG (app E11 E21) Ty
 < apply IH to Ty1 S2 RTy.

Subgoal 3:

Variables: X XTy TG Ty R E21 E11 E2 E1 Ty1
IH : forall X XTy TG E Ty R E',
       typeOf ((X, XTy)::TG) E Ty -> subst X R E E' * -> typeOf [] R XTy -> typeOf TG E' Ty
S : subst X R (app E1 E2) (app E11 E21) @
RTy : typeOf [] R XTy
S1 : subst X R E1 E11 *
S2 : subst X R E2 E21 *
Ty : typeOf ((X, XTy)::TG) E1 (arrowTy Ty1 Ty)
Ty1 : typeOf ((X, XTy)::TG) E2 Ty1
H1 : typeOf TG E11 (arrowTy Ty1 Ty)
H2 : typeOf TG E21 Ty1
============================
 typeOf TG (app E11 E21) Ty
 < search.

Subgoal 4:

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

Subgoal 4:

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

Subgoal 4.1:

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

Subgoal 4.2:

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

Subgoal 5:

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

Subgoal 5:

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

Subgoal 5.1:

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

Subgoal 5.2:

Variables: X XTy TG Ty R Y
IH : forall X XTy TG E Ty R E',
       typeOf ((X, XTy)::TG) E Ty -> subst X R E E' * -> typeOf [] R XTy -> typeOf TG E' Ty
S : subst X R (var Y) (var Y) @
RTy : typeOf [] R XTy
S1 : X = Y -> false
L : X = Y -> false
L1 : lookup TG Y Ty
============================
 typeOf TG (var Y) Ty
 < search.

Proof completed.
 < Prove mtc:shared_declarations:evalStep_type_preservation.

Subgoal 1:

Variables: Ty E2 E11 E1
IH : forall E Ty E', typeOf [] E Ty -> evalStep E E' * -> typeOf [] E' Ty
Ty : typeOf [] (app E1 E2) Ty
Ev : evalStep (app E1 E2) (app E11 E2) @
Ev1 : evalStep E1 E11 *
============================
 typeOf [] (app E11 E2) Ty
 < Ty: case Ty.

Subgoal 1:

Variables: Ty E2 E11 E1 Ty1
IH : forall E Ty E', typeOf [] E Ty -> evalStep E E' * -> typeOf [] E' Ty
Ev : evalStep (app E1 E2) (app E11 E2) @
Ev1 : evalStep E1 E11 *
Ty : typeOf [] E1 (arrowTy Ty1 Ty)
Ty1 : typeOf [] E2 Ty1
============================
 typeOf [] (app E11 E2) Ty
 < apply IH to Ty Ev1.

Subgoal 1:

Variables: Ty E2 E11 E1 Ty1
IH : forall E Ty E', typeOf [] E Ty -> evalStep E E' * -> typeOf [] E' Ty
Ev : evalStep (app E1 E2) (app E11 E2) @
Ev1 : evalStep E1 E11 *
Ty : typeOf [] E1 (arrowTy Ty1 Ty)
Ty1 : typeOf [] E2 Ty1
H1 : typeOf [] E11 (arrowTy Ty1 Ty)
============================
 typeOf [] (app E11 E2) Ty
 < search.

Subgoal 2:

Variables: Ty E21 E1 E2
IH : forall E Ty E', typeOf [] E Ty -> evalStep E E' * -> typeOf [] E' Ty
Ty : typeOf [] (app E1 E2) Ty
Ev : evalStep (app E1 E2) (app E1 E21) @
Ev1 : value E1
Ev2 : evalStep E2 E21 *
============================
 typeOf [] (app E1 E21) Ty
 < Ty: case Ty.

Subgoal 2:

Variables: Ty E21 E1 E2 Ty1
IH : forall E Ty E', typeOf [] E Ty -> evalStep E E' * -> typeOf [] E' Ty
Ev : evalStep (app E1 E2) (app E1 E21) @
Ev1 : value E1
Ev2 : evalStep E2 E21 *
Ty : typeOf [] E1 (arrowTy Ty1 Ty)
Ty1 : typeOf [] E2 Ty1
============================
 typeOf [] (app E1 E21) Ty
 < apply IH to Ty1 Ev2.

Subgoal 2:

Variables: Ty E21 E1 E2 Ty1
IH : forall E Ty E', typeOf [] E Ty -> evalStep E E' * -> typeOf [] E' Ty
Ev : evalStep (app E1 E2) (app E1 E21) @
Ev1 : value E1
Ev2 : evalStep E2 E21 *
Ty : typeOf [] E1 (arrowTy Ty1 Ty)
Ty1 : typeOf [] E2 Ty1
H1 : typeOf [] E21 Ty1
============================
 typeOf [] (app E1 E21) Ty
 < search.

Subgoal 3:

Variables: Ty E' E2 E1 Ty1 X
IH : forall E Ty E', typeOf [] E Ty -> evalStep E E' * -> typeOf [] E' Ty
Ty : typeOf [] (app (abs X Ty1 E1) E2) Ty
Ev : evalStep (app (abs X Ty1 E1) E2) E' @
Ev1 : value E2
Ev2 : subst X E2 E1 E'
============================
 typeOf [] E' Ty
 < Ty: case Ty.

Subgoal 3:

Variables: Ty E' E2 E1 Ty1 X Ty2
IH : forall E Ty E', typeOf [] E Ty -> evalStep E E' * -> typeOf [] E' Ty
Ev : evalStep (app (abs X Ty1 E1) E2) E' @
Ev1 : value E2
Ev2 : subst X E2 E1 E'
Ty : typeOf [] (abs X Ty1 E1) (arrowTy Ty2 Ty)
Ty1 : typeOf [] E2 Ty2
============================
 typeOf [] E' Ty
 < Ty: case Ty.

Subgoal 3:

Variables: Ty E' E2 E1 X Ty2
IH : forall E Ty E', typeOf [] E Ty -> evalStep E E' * -> typeOf [] E' Ty
Ev : evalStep (app (abs X Ty2 E1) E2) E' @
Ev1 : value E2
Ev2 : subst X E2 E1 E'
Ty1 : typeOf [] E2 Ty2
Ty : typeOf [(X, Ty2)] E1 Ty
============================
 typeOf [] E' Ty
 < apply subst_preservation to Ty Ev2 Ty1.

Subgoal 3:

Variables: Ty E' E2 E1 X Ty2
IH : forall E Ty E', typeOf [] E Ty -> evalStep E E' * -> typeOf [] E' Ty
Ev : evalStep (app (abs X Ty2 E1) E2) E' @
Ev1 : value E2
Ev2 : subst X E2 E1 E'
Ty1 : typeOf [] E2 Ty2
Ty : typeOf [(X, Ty2)] E1 Ty
H1 : typeOf [] E' Ty
============================
 typeOf [] E' Ty
 < search.

Proof completed.
 < Prove mtc:shared_declarations:canonical_form.

Subgoal 1:

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

Subgoal 1:

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

Proof completed.
 < Prove mtc:shared_declarations:subst_is.

Subgoal 1:

Variables: X R E1 Ty
IH : forall X R E E', is_e E -> is_e R -> subst X R E E' * -> is_e E'
IsE : is_e (abs X Ty E1)
IsR : is_e R
S : subst X R (abs X Ty E1) (abs X Ty E1) @
============================
 is_e (abs X Ty E1)
 < search.

Subgoal 2:

Variables: X R E2 Ty Y E1
IH : forall X R E E', is_e E -> is_e R -> subst X R E E' * -> is_e E'
IsE : is_e (abs Y Ty E1)
IsR : is_e R
S : subst X R (abs Y Ty E1) (abs Y Ty E2) @
S1 : X = Y -> false
S2 : subst X R E1 E2 *
============================
 is_e (abs Y Ty E2)
 < Is: case IsE.

Subgoal 2:

Variables: X R E2 Ty Y E1
IH : forall X R E E', is_e E -> is_e R -> subst X R E E' * -> is_e E'
IsR : is_e R
S : subst X R (abs Y Ty E1) (abs Y Ty E2) @
S1 : X = Y -> false
S2 : subst X R E1 E2 *
Is : is_string Y
Is1 : is_ty Ty
Is2 : is_e E1
============================
 is_e (abs Y Ty E2)
 < apply IH to _ _ S2.

Subgoal 2:

Variables: X R E2 Ty Y E1
IH : forall X R E E', is_e E -> is_e R -> subst X R E E' * -> is_e E'
IsR : is_e R
S : subst X R (abs Y Ty E1) (abs Y Ty E2) @
S1 : X = Y -> false
S2 : subst X R E1 E2 *
Is : is_string Y
Is1 : is_ty Ty
Is2 : is_e E1
H1 : is_e E2
============================
 is_e (abs Y Ty E2)
 < search.

Subgoal 3:

Variables: X R E21 E11 E2 E1
IH : forall X R E E', is_e E -> is_e R -> subst X R E E' * -> is_e E'
IsE : is_e (app E1 E2)
IsR : is_e R
S : subst X R (app E1 E2) (app E11 E21) @
S1 : subst X R E1 E11 *
S2 : subst X R E2 E21 *
============================
 is_e (app E11 E21)
 < case IsE.

Subgoal 3:

Variables: X R E21 E11 E2 E1
IH : forall X R E E', is_e E -> is_e R -> subst X R E E' * -> is_e E'
IsR : is_e R
S : subst X R (app E1 E2) (app E11 E21) @
S1 : subst X R E1 E11 *
S2 : subst X R E2 E21 *
H1 : is_e E1
H2 : is_e E2
============================
 is_e (app E11 E21)
 < apply IH to _ _ S1.

Subgoal 3:

Variables: X R E21 E11 E2 E1
IH : forall X R E E', is_e E -> is_e R -> subst X R E E' * -> is_e E'
IsR : is_e R
S : subst X R (app E1 E2) (app E11 E21) @
S1 : subst X R E1 E11 *
S2 : subst X R E2 E21 *
H1 : is_e E1
H2 : is_e E2
H3 : is_e E11
============================
 is_e (app E11 E21)
 < apply IH to _ _ S2.

Subgoal 3:

Variables: X R E21 E11 E2 E1
IH : forall X R E E', is_e E -> is_e R -> subst X R E E' * -> is_e E'
IsR : is_e R
S : subst X R (app E1 E2) (app E11 E21) @
S1 : subst X R E1 E11 *
S2 : subst X R E2 E21 *
H1 : is_e E1
H2 : is_e E2
H3 : is_e E11
H4 : is_e E21
============================
 is_e (app E11 E21)
 < search.

Subgoal 4:

Variables: X E'
IH : forall X R E E', is_e E -> is_e R -> subst X R E E' * -> is_e E'
IsE : is_e (var X)
IsR : is_e E'
S : subst X E' (var X) E' @
============================
 is_e E'
 < search.

Subgoal 5:

Variables: X R Y
IH : forall X R E E', is_e E -> is_e R -> subst X R E E' * -> is_e E'
IsE : is_e (var Y)
IsR : is_e R
S : subst X R (var Y) (var Y) @
S1 : X = Y -> false
============================
 is_e (var Y)
 < search.

Proof completed.
 < Prove mtc:shared_declarations:evalStep_is.

Subgoal 1:

Variables: E2 E11 E1
IH : forall E E', is_e E -> evalStep E E' * -> is_e E'
IsE : is_e (app E1 E2)
Ev : evalStep (app E1 E2) (app E11 E2) @
Ev1 : evalStep E1 E11 *
============================
 is_e (app E11 E2)
 < case IsE.

Subgoal 1:

Variables: E2 E11 E1
IH : forall E E', is_e E -> evalStep E E' * -> is_e E'
Ev : evalStep (app E1 E2) (app E11 E2) @
Ev1 : evalStep E1 E11 *
H1 : is_e E1
H2 : is_e E2
============================
 is_e (app E11 E2)
 < apply IH to _ Ev1.

Subgoal 1:

Variables: E2 E11 E1
IH : forall E E', is_e E -> evalStep E E' * -> is_e E'
Ev : evalStep (app E1 E2) (app E11 E2) @
Ev1 : evalStep E1 E11 *
H1 : is_e E1
H2 : is_e E2
H3 : is_e E11
============================
 is_e (app E11 E2)
 < search.

Subgoal 2:

Variables: E21 E1 E2
IH : forall E E', is_e E -> evalStep E E' * -> is_e E'
IsE : is_e (app E1 E2)
Ev : evalStep (app E1 E2) (app E1 E21) @
Ev1 : value E1
Ev2 : evalStep E2 E21 *
============================
 is_e (app E1 E21)
 < case IsE.

Subgoal 2:

Variables: E21 E1 E2
IH : forall E E', is_e E -> evalStep E E' * -> is_e E'
Ev : evalStep (app E1 E2) (app E1 E21) @
Ev1 : value E1
Ev2 : evalStep E2 E21 *
H1 : is_e E1
H2 : is_e E2
============================
 is_e (app E1 E21)
 < apply IH to _ Ev2.

Subgoal 2:

Variables: E21 E1 E2
IH : forall E E', is_e E -> evalStep E E' * -> is_e E'
Ev : evalStep (app E1 E2) (app E1 E21) @
Ev1 : value E1
Ev2 : evalStep E2 E21 *
H1 : is_e E1
H2 : is_e E2
H3 : is_e E21
============================
 is_e (app E1 E21)
 < search.

Subgoal 3:

Variables: E' E2 E1 Ty X
IH : forall E E', is_e E -> evalStep E E' * -> is_e E'
IsE : is_e (app (abs X Ty E1) E2)
Ev : evalStep (app (abs X Ty E1) E2) E' @
Ev1 : value E2
Ev2 : subst X E2 E1 E'
============================
 is_e E'
 < Is: case IsE.

Subgoal 3:

Variables: E' E2 E1 Ty X
IH : forall E E', is_e E -> evalStep E E' * -> is_e E'
Ev : evalStep (app (abs X Ty E1) E2) E' @
Ev1 : value E2
Ev2 : subst X E2 E1 E'
Is : is_e (abs X Ty E1)
Is1 : is_e E2
============================
 is_e E'
 < case Is.

Subgoal 3:

Variables: E' E2 E1 Ty X
IH : forall E E', is_e E -> evalStep E E' * -> is_e E'
Ev : evalStep (app (abs X Ty E1) E2) E' @
Ev1 : value E2
Ev2 : subst X E2 E1 E'
Is1 : is_e E2
H1 : is_string X
H2 : is_ty Ty
H3 : is_e E1
============================
 is_e E'
 < apply subst_is to _ _ Ev2.

Subgoal 3:

Variables: E' E2 E1 Ty X
IH : forall E E', is_e E -> evalStep E E' * -> is_e E'
Ev : evalStep (app (abs X Ty E1) E2) E' @
Ev1 : value E2
Ev2 : subst X E2 E1 E'
Is1 : is_e E2
H1 : is_string X
H2 : is_ty Ty
H3 : is_e E1
H4 : is_e E'
============================
 is_e E'
 < search.

Proof completed.
 < Prove mtc:shared_declarations:subst_total.

Subgoal 2:

Variables: X R E1 Ty S
IH : forall X R E,
       is_e E * -> is_string X -> is_e R -> exists E', subst X R E E'
IsE : is_e (abs S Ty E1) @
IsX : is_string X
IsR : is_e R
IsE1 : is_string S
IsE2 : is_ty Ty
IsE3 : is_e E1 *
============================
 exists E', subst X R (abs S Ty E1) E'
 < Or: apply is_string_eq_or_not to IsX IsE1.

Subgoal 2:

Variables: X R E1 Ty S
IH : forall X R E,
       is_e E * -> is_string X -> is_e R -> exists E', subst X R E E'
IsE : is_e (abs S Ty E1) @
IsX : is_string X
IsR : is_e R
IsE1 : is_string S
IsE2 : is_ty Ty
IsE3 : is_e E1 *
Or : X = S \/ (X = S -> false)
============================
 exists E', subst X R (abs S Ty E1) E'
 < case Or.

Subgoal 2.1:

Variables: R E1 Ty S
IH : forall X R E,
       is_e E * -> is_string X -> is_e R -> exists E', subst X R E E'
IsE : is_e (abs S Ty E1) @
IsX : is_string S
IsR : is_e R
IsE1 : is_string S
IsE2 : is_ty Ty
IsE3 : is_e E1 *
============================
 exists E', subst S R (abs S Ty E1) E'
 < search.

Subgoal 2.2:

Variables: X R E1 Ty S
IH : forall X R E,
       is_e E * -> is_string X -> is_e R -> exists E', subst X R E E'
IsE : is_e (abs S Ty E1) @
IsX : is_string X
IsR : is_e R
IsE1 : is_string S
IsE2 : is_ty Ty
IsE3 : is_e E1 *
H1 : X = S -> false
============================
 exists E', subst X R (abs S Ty E1) E'
 < apply IH to IsE3 IsX IsR.

Subgoal 2.2:

Variables: X R E1 Ty S E'
IH : forall X R E,
       is_e E * -> is_string X -> is_e R -> exists E', subst X R E E'
IsE : is_e (abs S Ty E1) @
IsX : is_string X
IsR : is_e R
IsE1 : is_string S
IsE2 : is_ty Ty
IsE3 : is_e E1 *
H1 : X = S -> false
H2 : subst X R E1 E'
============================
 exists E', subst X R (abs S Ty E1) E'
 < search.

Subgoal 3:

Variables: X R E2 E1
IH : forall X R E,
       is_e E * -> is_string X -> is_e R -> exists E', subst X R E E'
IsE : is_e (app E1 E2) @
IsX : is_string X
IsR : is_e R
IsE1 : is_e E1 *
IsE2 : is_e E2 *
============================
 exists E', subst X R (app E1 E2) E'
 < apply IH to IsE1 IsX IsR.

Subgoal 3:

Variables: X R E2 E1 E'
IH : forall X R E,
       is_e E * -> is_string X -> is_e R -> exists E', subst X R E E'
IsE : is_e (app E1 E2) @
IsX : is_string X
IsR : is_e R
IsE1 : is_e E1 *
IsE2 : is_e E2 *
H1 : subst X R E1 E'
============================
 exists E', subst X R (app E1 E2) E'
 < apply IH to IsE2 IsX IsR.

Subgoal 3:

Variables: X R E2 E1 E' E'1
IH : forall X R E,
       is_e E * -> is_string X -> is_e R -> exists E', subst X R E E'
IsE : is_e (app E1 E2) @
IsX : is_string X
IsR : is_e R
IsE1 : is_e E1 *
IsE2 : is_e E2 *
H1 : subst X R E1 E'
H2 : subst X R E2 E'1
============================
 exists E', subst X R (app E1 E2) E'
 < search.

Subgoal 4:

Variables: X R S
IH : forall X R E,
       is_e E * -> is_string X -> is_e R -> exists E', subst X R E E'
IsE : is_e (var S) @
IsX : is_string X
IsR : is_e R
IsE1 : is_string S
============================
 exists E', subst X R (var S) E'
 < Or: apply is_string_eq_or_not to IsX IsE1.

Subgoal 4:

Variables: X R S
IH : forall X R E,
       is_e E * -> is_string X -> is_e R -> exists E', subst X R E E'
IsE : is_e (var S) @
IsX : is_string X
IsR : is_e R
IsE1 : is_string S
Or : X = S \/ (X = S -> false)
============================
 exists E', subst X R (var S) E'
 < case Or.

Subgoal 4.1:

Variables: R S
IH : forall X R E,
       is_e E * -> is_string X -> is_e R -> exists E', subst X R E E'
IsE : is_e (var S) @
IsX : is_string S
IsR : is_e R
IsE1 : is_string S
============================
 exists E', subst S R (var S) E'
 < search.

Subgoal 4.2:

Variables: X R S
IH : forall X R E,
       is_e E * -> is_string X -> is_e R -> exists E', subst X R E E'
IsE : is_e (var S) @
IsX : is_string X
IsR : is_e R
IsE1 : is_string S
H1 : X = S -> false
============================
 exists E', subst X R (var S) E'
 < search.

Proof completed.
 < Prove mtc:shared_declarations:progress.

Subgoal 1:

Variables: Ty2 Ty1 E1 X
IH : forall E Ty,
       is_e E -> typeOf [] E Ty * -> value E \/ (exists E', evalStep E E')
IsE : is_e (abs X Ty1 E1)
Ty : typeOf [] (abs X Ty1 E1) (arrowTy Ty1 Ty2) @
Ty1 : typeOf [(X, Ty1)] E1 Ty2 *
============================
 value (abs X Ty1 E1) \/ (exists E', evalStep (abs X Ty1 E1) E')
 < search.

Subgoal 2:

Variables: Ty Ty1 E2 E1
IH : forall E Ty,
       is_e E -> typeOf [] E Ty * -> value E \/ (exists E', evalStep E E')
IsE : is_e (app E1 E2)
Ty : typeOf [] (app E1 E2) Ty @
Ty1 : typeOf [] E1 (arrowTy Ty1 Ty) *
Ty2 : typeOf [] E2 Ty1 *
============================
 value (app E1 E2) \/ (exists E', evalStep (app E1 E2) E')
 < Is: case IsE.

Subgoal 2:

Variables: Ty Ty1 E2 E1
IH : forall E Ty,
       is_e E -> typeOf [] E Ty * -> value E \/ (exists E', evalStep E E')
Ty : typeOf [] (app E1 E2) Ty @
Ty1 : typeOf [] E1 (arrowTy Ty1 Ty) *
Ty2 : typeOf [] E2 Ty1 *
Is : is_e E1
Is1 : is_e E2
============================
 value (app E1 E2) \/ (exists E', evalStep (app E1 E2) E')
 < Or1: apply IH to _ Ty1.

Subgoal 2:

Variables: Ty Ty1 E2 E1
IH : forall E Ty,
       is_e E -> typeOf [] E Ty * -> value E \/ (exists E', evalStep E E')
Ty : typeOf [] (app E1 E2) Ty @
Ty1 : typeOf [] E1 (arrowTy Ty1 Ty) *
Ty2 : typeOf [] E2 Ty1 *
Is : is_e E1
Is1 : is_e E2
Or1 : value E1 \/ (exists E', evalStep E1 E')
============================
 value (app E1 E2) \/ (exists E', evalStep (app E1 E2) E')
 < Or2: apply IH to _ Ty2.

Subgoal 2:

Variables: Ty Ty1 E2 E1
IH : forall E Ty,
       is_e E -> typeOf [] E Ty * -> value E \/ (exists E', evalStep E E')
Ty : typeOf [] (app E1 E2) Ty @
Ty1 : typeOf [] E1 (arrowTy Ty1 Ty) *
Ty2 : typeOf [] E2 Ty1 *
Is : is_e E1
Is1 : is_e E2
Or1 : value E1 \/ (exists E', evalStep E1 E')
Or2 : value E2 \/ (exists E', evalStep E2 E')
============================
 value (app E1 E2) \/ (exists E', evalStep (app E1 E2) E')
 < Ev1: case Or1.

Subgoal 2.1:

Variables: Ty Ty1 E2 E1
IH : forall E Ty,
       is_e E -> typeOf [] E Ty * -> value E \/ (exists E', evalStep E E')
Ty : typeOf [] (app E1 E2) Ty @
Ty1 : typeOf [] E1 (arrowTy Ty1 Ty) *
Ty2 : typeOf [] E2 Ty1 *
Is : is_e E1
Is1 : is_e E2
Or2 : value E2 \/ (exists E', evalStep E2 E')
Ev1 : value E1
============================
 value (app E1 E2) \/ (exists E', evalStep (app E1 E2) E')
 < Ev2: case Or2.

Subgoal 2.1.1:

Variables: Ty Ty1 E2 E1
IH : forall E Ty,
       is_e E -> typeOf [] E Ty * -> value E \/ (exists E', evalStep E E')
Ty : typeOf [] (app E1 E2) Ty @
Ty1 : typeOf [] E1 (arrowTy Ty1 Ty) *
Ty2 : typeOf [] E2 Ty1 *
Is : is_e E1
Is1 : is_e E2
Ev1 : value E1
Ev2 : value E2
============================
 value (app E1 E2) \/ (exists E', evalStep (app E1 E2) E')
 < C: apply canonical_form to Ev1 Ty1.

Subgoal 2.1.1:

Variables: Ty Ty1 E2 E1
IH : forall E Ty,
       is_e E -> typeOf [] E Ty * -> value E \/ (exists E', evalStep E E')
Ty : typeOf [] (app E1 E2) Ty @
Ty1 : typeOf [] E1 (arrowTy Ty1 Ty) *
Ty2 : typeOf [] E2 Ty1 *
Is : is_e E1
Is1 : is_e E2
Ev1 : value E1
Ev2 : value E2
C : canon (arrowTy Ty1 Ty) E1
============================
 value (app E1 E2) \/ (exists E', evalStep (app E1 E2) E')
 < case C.

Subgoal 2.1.1:

Variables: Ty Ty1 E2 E3 X
IH : forall E Ty,
       is_e E -> typeOf [] E Ty * -> value E \/ (exists E', evalStep E E')
Ty : typeOf [] (app (abs X Ty1 E3) E2) Ty @
Ty1 : typeOf [] (abs X Ty1 E3) (arrowTy Ty1 Ty) *
Ty2 : typeOf [] E2 Ty1 *
Is : is_e (abs X Ty1 E3)
Is1 : is_e E2
Ev1 : value (abs X Ty1 E3)
Ev2 : value E2
============================
 value (app (abs X Ty1 E3) E2) \/
 (exists E', evalStep (app (abs X Ty1 E3) E2) E')
 < IsAbs: case Is.

Subgoal 2.1.1:

Variables: Ty Ty1 E2 E3 X
IH : forall E Ty,
       is_e E -> typeOf [] E Ty * -> value E \/ (exists E', evalStep E E')
Ty : typeOf [] (app (abs X Ty1 E3) E2) Ty @
Ty1 : typeOf [] (abs X Ty1 E3) (arrowTy Ty1 Ty) *
Ty2 : typeOf [] E2 Ty1 *
Is1 : is_e E2
Ev1 : value (abs X Ty1 E3)
Ev2 : value E2
IsAbs : is_string X
IsAbs1 : is_ty Ty1
IsAbs2 : is_e E3
============================
 value (app (abs X Ty1 E3) E2) \/
 (exists E', evalStep (app (abs X Ty1 E3) E2) E')
 < apply subst_total to IsAbs2 IsAbs Is1.

Subgoal 2.1.1:

Variables: Ty Ty1 E2 E3 X E'
IH : forall E Ty,
       is_e E -> typeOf [] E Ty * -> value E \/ (exists E', evalStep E E')
Ty : typeOf [] (app (abs X Ty1 E3) E2) Ty @
Ty1 : typeOf [] (abs X Ty1 E3) (arrowTy Ty1 Ty) *
Ty2 : typeOf [] E2 Ty1 *
Is1 : is_e E2
Ev1 : value (abs X Ty1 E3)
Ev2 : value E2
IsAbs : is_string X
IsAbs1 : is_ty Ty1
IsAbs2 : is_e E3
H1 : subst X E2 E3 E'
============================
 value (app (abs X Ty1 E3) E2) \/
 (exists E', evalStep (app (abs X Ty1 E3) E2) E')
 < search.

Subgoal 2.1.2:

Variables: Ty Ty1 E2 E1 E'
IH : forall E Ty,
       is_e E -> typeOf [] E Ty * -> value E \/ (exists E', evalStep E E')
Ty : typeOf [] (app E1 E2) Ty @
Ty1 : typeOf [] E1 (arrowTy Ty1 Ty) *
Ty2 : typeOf [] E2 Ty1 *
Is : is_e E1
Is1 : is_e E2
Ev1 : value E1
Ev2 : evalStep E2 E'
============================
 value (app E1 E2) \/ (exists E', evalStep (app E1 E2) E')
 < search.

Subgoal 2.2:

Variables: Ty Ty1 E2 E1 E'
IH : forall E Ty,
       is_e E -> typeOf [] E Ty * -> value E \/ (exists E', evalStep E E')
Ty : typeOf [] (app E1 E2) Ty @
Ty1 : typeOf [] E1 (arrowTy Ty1 Ty) *
Ty2 : typeOf [] E2 Ty1 *
Is : is_e E1
Is1 : is_e E2
Or2 : value E2 \/ (exists E', evalStep E2 E')
Ev1 : evalStep E1 E'
============================
 value (app E1 E2) \/ (exists E', evalStep (app E1 E2) E')
 < search.

Subgoal 3:

Variables: Ty X
IH : forall E Ty,
       is_e E -> typeOf [] E Ty * -> value E \/ (exists E', evalStep E E')
IsE : is_e (var X)
Ty : typeOf [] (var X) Ty @
Ty1 : lookup [] X Ty
============================
 value (var X) \/ (exists E', evalStep (var X) E')
 < case Ty1.

Proof completed.
Back to example home