In this lecture, we will prove that the simply typed lambda calculus is terminating. We also add natural numbers to the language.
Here, we demonstrate the use of the Rec operator in Coq. Our language will also have such a Rec operator. The Rec operator is powerful enough to define addition, multiplication, and exponentiation.
Fixpoint rec {A} (n : nat) (x : A) (f : A -> A) : A := match n with | 0 => x | S n => f (rec n x f) end. Definition double n := rec n 0 (fun x => S (S x)).Definition add n m := rec n m (fun x => S x).Definition mul n m := rec n 0 (fun x => add m x).Definition pow n m := rec m 1 (fun x => mul n x).When using rec with A := nat, we can only do primitive recursion. By using the rec operator at type A := nat -> nat, we can go beyond, and define the Ackermann function.
Definition ack m := rec m S (fun f => fun n => rec (S n) 1 f).(* Useful tactics for simplifying equalities *) Ltac simpeq := repeat match goal with | _ => congruence || (progress subst) | H : ?x = ?x |- _ => clear H | H : _ = _ |- _ => progress injection H as H end. Ltac inv H := inversion H; clear H; simpeq. (* Utilities on environments/contexts *)Definition empty {T} : string -> option T := fun _ => None. Definition insert {T} (x : string) (t : T) (f : string -> option T) : string -> option T := fun x' => if string_dec x x' then Some t else f x'. Definition delete {T} (x : string) (f : string -> option T) : string -> option T := fun x' => if string_dec x x' then None else f x'. (* fun_eq lets us avoid the function extensionality axiom *) Definition fun_eq {A B} (f g : A -> B) := forall x, f x = g x. Notation "f == g" := (fun_eq f g) (at level 70). Ltac simpfun := (unfold fun_eq, delete, insert in *); (repeat (solve [eauto] || destruct string_dec || simpeq || intro)). (* We can prove all the following lemmas using simpfun. Now that we have simpfun, we don't even need the lemmas, we can just do simpfun. Lemma fun_eq_refl {A B} (f : A -> B) : f == f. Proof. simpfun. Defined. Lemma fun_eq_sym {A B} (f g : A -> B) : f == g -> g == f. Proof. simpfun. Defined. Lemma delete_insert {T} x v (env : string -> option T) : delete x (insert x v env) == delete x env. Proof. simpfun. Defined. Lemma insert_delete {T} x v (env : string -> option T) : insert x v (delete x env) == insert x v env. Proof. simpfun. Defined. Lemma delete_delete {T} x (env : string -> option T) : delete x (delete x env) == delete x env. Proof. simpfun. Defined. Lemma delete_delete_comm {T} x y (env : string -> option T) : x <> y -> delete x (delete y env) == delete y (delete x env). Proof. simpfun. Defined. Lemma delete_insert_comm {T} x y v (env : string -> option T) : x <> y -> delete x (insert y v env) == insert y v (delete x env). Proof. simpfun. Defined. *)
Inductive expr :=
| Var (x : string)
| Lam (x : string) (e : expr)
| App (e1 e2 : expr)
| Zero : expr
| Succ (e : expr)
| Rec (e1 e2 e3 : expr).
Inductive ty := | Nat : ty | Fun (t1 t2 : ty). Definition ctx := string -> option ty. Inductive typed : ctx -> expr -> ty -> Prop := | Typed_Var (x : string) (t : ty) (Gamma : ctx) : Gamma x = Some t -> typed Gamma (Var x) t | Typed_Lam (x : string) (e : expr) (t1 t2 : ty) (Gamma : ctx) : typed (insert x t1 Gamma) e t2 -> typed Gamma (Lam x e) (Fun t1 t2) | Typed_App (e1 e2 : expr) (t1 t2 : ty) (Gamma : ctx) : typed Gamma e1 (Fun t1 t2) -> typed Gamma e2 t1 -> typed Gamma (App e1 e2) t2 | Typed_Zero (Gamma : ctx) : typed Gamma Zero Nat | Typed_Succ (e : expr) (Gamma : ctx) : typed Gamma e Nat -> typed Gamma (Succ e) Nat | Typed_Rec (e1 e2 e3 : expr) (Gamma : ctx) (t : ty) : typed Gamma e1 Nat -> typed Gamma e2 t -> typed Gamma e3 (Fun t t) -> typed Gamma (Rec e1 e2 e3) t.
Substitution
Fixpoint subst (x : string) (v : expr) (e : expr) : expr :=
match e with
| Var y => if string_dec x y then v else e
| Lam y e => Lam y (if string_dec x y then e else subst x v e)
| App e1 e2 => App (subst x v e1) (subst x v e2)
| Zero => Zero
| Succ e => Succ (subst x v e)
| Rec e1 e2 e3 => Rec (subst x v e1) (subst x v e2) (subst x v e3)
end.
Values
Inductive value : expr -> Prop :=
| Val_Lam (x : string) (e : expr) :
value (Lam x e)
| Val_Zero :
value Zero
| Val_Succ (e : expr) :
value e ->
value (Succ e).
Small-step Semantics
Inductive step : expr -> expr -> Prop :=
| Step_App1 (e1 e1' e2 : expr) :
step e1 e1' ->
step (App e1 e2) (App e1' e2)
| Step_App2 (e1 e2 e2' : expr) :
step e2 e2' ->
step (App e1 e2) (App e1 e2')
| Step_AppLam (x : string) (v e : expr) :
value v ->
step (App (Lam x e) v) (subst x v e)
| Step_Succ1 (e e' : expr) :
step e e' ->
step (Succ e) (Succ e')
| Step_Rec1 (e1 e1' e2 e3 : expr) :
step e1 e1' ->
step (Rec e1 e2 e3) (Rec e1' e2 e3)
| Step_Rec2 (e1 e2 e2' e3 : expr) :
step e2 e2' ->
step (Rec e1 e2 e3) (Rec e1 e2' e3)
| Step_Rec3 (e1 e2 e3 e3' : expr) :
step e3 e3' ->
step (Rec e1 e2 e3) (Rec e1 e2 e3')
| Step_RecZero (e2 e3 : expr) :
value e2 -> value e3 ->
step (Rec Zero e2 e3) e2
| Step_RecSucc (e1 e2 e3 : expr) :
value e1 -> value e2 -> value e3 ->
step (Rec (Succ e1) e2 e3) (Rec e1 (App e3 e2) e3).
Inductive rtc {A} (R : A -> A -> Prop) : A -> A -> Prop := | rtc_refl (x : A) : rtc R x x | rtc_once (x y z : A) : R x y -> rtc R y z -> rtc R x z. Definition terminates (e : expr) := exists e', rtc step e e' /\ value e'.
(* Main proof: semantic typing of values and expressions *) Fixpoint nat_to_expr (n : nat) : expr := match n with | 0 => Zero | S n => Succ (nat_to_expr n) end. Definition closed e := forall x v, subst x v e = e. Fixpoint value_ok (e : expr) (t : ty) := match t with | Nat => exists n, e = nat_to_expr n | Fun t1 t2 => closed e /\ exists x ebody, e = Lam x ebody /\ forall v, value_ok v t1 -> exists e', rtc step (subst x v ebody) e' /\ value_ok e' t2 end. Definition expr_ok (e : expr) (t : ty) := exists e', rtc step e e' /\ value_ok e' t. (* Helper lemmas about steps, value_ok, and expr_ok *)A: Type
R: A -> A -> Prop
x, y, z: Artc R x y -> rtc R y z -> rtc R x zinduction 1; eauto using rtc_once. Defined.A: Type
R: A -> A -> Prop
x, y, z: Artc R x y -> rtc R y z -> rtc R x ze, e': exprrtc step e e' -> rtc step (Succ e) (Succ e')induction 1; eauto using rtc_refl, rtc_once, Step_Succ1. Defined.e, e': exprrtc step e e' -> rtc step (Succ e) (Succ e')e1, e1', e2, e2', e3, e3': exprrtc step e1 e1' -> rtc step e2 e2' -> rtc step e3 e3' -> rtc step (Rec e1 e2 e3) (Rec e1' e2' e3')e1, e1', e2, e2', e3, e3': exprrtc step e1 e1' -> rtc step e2 e2' -> rtc step e3 e3' -> rtc step (Rec e1 e2 e3) (Rec e1' e2' e3')e2, e2', e3, e3', x: exprrtc step e2 e2' -> rtc step e3 e3' -> rtc step (Rec x e2 e3) (Rec x e2' e3')e3, e3', x, x0: exprrtc step e3 e3' -> rtc step (Rec x x0 e3) (Rec x x0 e3')eapply rtc_refl. Defined.x, x0, x1: exprrtc step (Rec x x0 x1) (Rec x x0 x1)e1, e1', e2, e2': exprrtc step e1 e1' -> rtc step e2 e2' -> rtc step (App e1 e2) (App e1' e2')e1, e1', e2, e2': exprrtc step e1 e1' -> rtc step e2 e2' -> rtc step (App e1 e2) (App e1' e2')e2, e2', x: exprrtc step e2 e2' -> rtc step (App x e2) (App x e2')eapply rtc_refl. Defined.x, x0: exprrtc step (App x x0) (App x x0)e, e': expr
t: tyrtc step e e' -> expr_ok e' t -> expr_ok e te, e': expr
t: tyrtc step e e' -> expr_ok e' t -> expr_ok e te, e': expr
t: ty
Hstep: rtc step e e'
e'': expr
Hrtc: rtc step e' e''
Hval: value_ok e'' texpr_ok e tsplit; eauto using rtc_trans. Defined.e, e': expr
t: ty
Hstep: rtc step e e'
e'': expr
Hrtc: rtc step e' e''
Hval: value_ok e'' trtc step e e'' /\ value_ok e'' tv: expr
t: tyvalue_ok v t -> value vv: expr
t: tyvalue_ok v t -> value vv: expr
H: exists n : nat, v = nat_to_expr nvalue vv: expr
t1, t2: ty
H: closed v /\ (exists (x : string) (ebody : expr), v = Lam x ebody /\ (forall v : expr, value_ok v t1 -> exists e' : expr, rtc step (subst x v ebody) e' /\ value_ok e' t2))value vv: expr
H: exists n : nat, v = nat_to_expr nvalue vinduction n; simpl; constructor; auto.n: natvalue (nat_to_expr n)v: expr
t1, t2: ty
H: closed v /\ (exists (x : string) (ebody : expr), v = Lam x ebody /\ (forall v : expr, value_ok v t1 -> exists e' : expr, rtc step (subst x v ebody) e' /\ value_ok e' t2))value vconstructor. Defined.t1, t2: ty
x: string
ebody: expr
Hcloseded: closed (Lam x ebody)
H: forall v : expr, value_ok v t1 -> exists e' : expr, rtc step (subst x v ebody) e' /\ value_ok e' t2value (Lam x ebody)v: expr
t: tyvalue_ok v t -> expr_ok v tv: expr
t: tyvalue_ok v t -> expr_ok v tv: expr
t: ty
H: value_ok v texpr_ok v tv: expr
t: ty
H: value_ok v trtc step v v /\ value_ok v teapply rtc_refl. Defined.v: expr
t: ty
H: value_ok v trtc step v vn: natvalue (nat_to_expr n)induction n; simpl; constructor; auto. Defined.n: natvalue (nat_to_expr n)v1, v2: expr
t1, t2: tyvalue_ok v1 (Fun t1 t2) -> value_ok v2 t1 -> expr_ok (App v1 v2) t2v1, v2: expr
t1, t2: tyvalue_ok v1 (Fun t1 t2) -> value_ok v2 t1 -> expr_ok (App v1 v2) t2v1, v2: expr
t1, t2: ty
Hv1: value_ok v1 (Fun t1 t2)
Hv2: value_ok v2 t1expr_ok (App v1 v2) t2v1, v2: expr
t1, t2: ty
Hv1: closed v1 /\ (exists (x : string) (ebody : expr), v1 = Lam x ebody /\ (forall v : expr, value_ok v t1 -> exists e' : expr, rtc step (subst x v ebody) e' /\ value_ok e' t2))
Hv2: value_ok v2 t1expr_ok (App v1 v2) t2v2: expr
t1, t2: ty
x: string
ebody: expr
Hcloseded: closed (Lam x ebody)
H: forall v : expr, value_ok v t1 -> exists e' : expr, rtc step (subst x v ebody) e' /\ value_ok e' t2
Hv2: value_ok v2 t1expr_ok (App (Lam x ebody) v2) t2v2: expr
t1, t2: ty
x: string
ebody: expr
Hcloseded: closed (Lam x ebody)
H: forall v : expr, value_ok v t1 -> exists e' : expr, rtc step (subst x v ebody) e' /\ value_ok e' t2
Hv2: value_ok v2 t1rtc step (App (Lam x ebody) v2) ?e'v2: expr
t1, t2: ty
x: string
ebody: expr
Hcloseded: closed (Lam x ebody)
H: forall v : expr, value_ok v t1 -> exists e' : expr, rtc step (subst x v ebody) e' /\ value_ok e' t2
Hv2: value_ok v2 t1expr_ok ?e' t2eapply rtc_once; [apply Step_AppLam | apply rtc_refl]; eauto using value_ok_value.v2: expr
t1, t2: ty
x: string
ebody: expr
Hcloseded: closed (Lam x ebody)
H: forall v : expr, value_ok v t1 -> exists e' : expr, rtc step (subst x v ebody) e' /\ value_ok e' t2
Hv2: value_ok v2 t1rtc step (App (Lam x ebody) v2) ?e'v2: expr
t1, t2: ty
x: string
ebody: expr
Hcloseded: closed (Lam x ebody)
H: forall v : expr, value_ok v t1 -> exists e' : expr, rtc step (subst x v ebody) e' /\ value_ok e' t2
Hv2: value_ok v2 t1expr_ok (subst x v2 ebody) t2auto. Defined.v2: expr
t1, t2: ty
x: string
ebody: expr
Hcloseded: closed (Lam x ebody)
H: forall v : expr, value_ok v t1 -> exists e' : expr, rtc step (subst x v ebody) e' /\ value_ok e' t2
Hv2: value_ok v2 t1value_ok v2 t1n: nat
v1, v2: expr
t: tyvalue_ok v1 t -> value_ok v2 (Fun t t) -> expr_ok (Rec (nat_to_expr n) v1 v2) tn: nat
v1, v2: expr
t: tyvalue_ok v1 t -> value_ok v2 (Fun t t) -> expr_ok (Rec (nat_to_expr n) v1 v2) tn: nat
v1, v2: expr
t: ty
Hv1: value_ok v1 t
Hv2: value_ok v2 (Fun t t)expr_ok (Rec (nat_to_expr n) v1 v2) tn: nat
v2: expr
t: ty
Hv2: value_ok v2 (Fun t t)forall v1 : expr, value_ok v1 t -> expr_ok (Rec (nat_to_expr n) v1 v2) tv2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
v1: expr
Hv1: value_ok v1 texpr_ok (Rec Zero v1 v2) tn: nat
v2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
IHn: forall v1 : expr, value_ok v1 t -> expr_ok (Rec (nat_to_expr n) v1 v2) t
v1: expr
Hv1: value_ok v1 texpr_ok (Rec (Succ (nat_to_expr n)) v1 v2) tv2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
v1: expr
Hv1: value_ok v1 texpr_ok (Rec Zero v1 v2) tv2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
v1: expr
Hv1: value_ok v1 trtc step (Rec Zero v1 v2) ?e'v2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
v1: expr
Hv1: value_ok v1 texpr_ok ?e' teapply rtc_once; [apply Step_RecZero | apply rtc_refl]; eauto using value_ok_value.v2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
v1: expr
Hv1: value_ok v1 trtc step (Rec Zero v1 v2) ?e'v2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
v1: expr
Hv1: value_ok v1 texpr_ok v1 teauto.v2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
v1: expr
Hv1: value_ok v1 tvalue_ok v1 tn: nat
v2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
IHn: forall v1 : expr, value_ok v1 t -> expr_ok (Rec (nat_to_expr n) v1 v2) t
v1: expr
Hv1: value_ok v1 texpr_ok (Rec (Succ (nat_to_expr n)) v1 v2) tn: nat
v2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
IHn: forall v1 : expr, value_ok v1 t -> expr_ok (Rec (nat_to_expr n) v1 v2) t
v1: expr
Hv1: value_ok v1 trtc step (Rec (Succ (nat_to_expr n)) v1 v2) ?e'n: nat
v2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
IHn: forall v1 : expr, value_ok v1 t -> expr_ok (Rec (nat_to_expr n) v1 v2) t
v1: expr
Hv1: value_ok v1 texpr_ok ?e' teapply rtc_once; [apply Step_RecSucc | apply rtc_refl]; eauto using nat_to_expr_value, value_ok_value.n: nat
v2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
IHn: forall v1 : expr, value_ok v1 t -> expr_ok (Rec (nat_to_expr n) v1 v2) t
v1: expr
Hv1: value_ok v1 trtc step (Rec (Succ (nat_to_expr n)) v1 v2) ?e'n: nat
v2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
IHn: forall v1 : expr, value_ok v1 t -> expr_ok (Rec (nat_to_expr n) v1 v2) t
v1: expr
Hv1: value_ok v1 texpr_ok (Rec (nat_to_expr n) (App v2 v1) v2) tn: nat
v2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
IHn: forall v1 : expr, value_ok v1 t -> expr_ok (Rec (nat_to_expr n) v1 v2) t
v1: expr
Hv1: value_ok v1 texpr_ok (App v2 v1) tn: nat
v2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
IHn: forall v1 : expr, value_ok v1 t -> expr_ok (Rec (nat_to_expr n) v1 v2) t
v1: expr
Hv1: value_ok v1 t
H: expr_ok (App v2 v1) texpr_ok (Rec (nat_to_expr n) (App v2 v1) v2) teapply value_ok_App; eauto.n: nat
v2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
IHn: forall v1 : expr, value_ok v1 t -> expr_ok (Rec (nat_to_expr n) v1 v2) t
v1: expr
Hv1: value_ok v1 texpr_ok (App v2 v1) tn: nat
v2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
IHn: forall v1 : expr, value_ok v1 t -> expr_ok (Rec (nat_to_expr n) v1 v2) t
v1: expr
Hv1: value_ok v1 t
H: expr_ok (App v2 v1) texpr_ok (Rec (nat_to_expr n) (App v2 v1) v2) tn: nat
v2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
IHn: forall v1 : expr, value_ok v1 t -> expr_ok (Rec (nat_to_expr n) v1 v2) t
v1: expr
Hv1: value_ok v1 t
e': expr
Hstep: rtc step (App v2 v1) e'
Hval: value_ok e' texpr_ok (Rec (nat_to_expr n) (App v2 v1) v2) tn: nat
v2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
IHn: forall v1 : expr, value_ok v1 t -> expr_ok (Rec (nat_to_expr n) v1 v2) t
v1: expr
Hv1: value_ok v1 t
e': expr
Hstep: rtc step (App v2 v1) e'
Hval: value_ok e' trtc step (Rec (nat_to_expr n) (App v2 v1) v2) ?e'n: nat
v2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
IHn: forall v1 : expr, value_ok v1 t -> expr_ok (Rec (nat_to_expr n) v1 v2) t
v1: expr
Hv1: value_ok v1 t
e': expr
Hstep: rtc step (App v2 v1) e'
Hval: value_ok e' texpr_ok ?e' teapply rtc_step_Rec; eauto; eauto using rtc_refl.n: nat
v2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
IHn: forall v1 : expr, value_ok v1 t -> expr_ok (Rec (nat_to_expr n) v1 v2) t
v1: expr
Hv1: value_ok v1 t
e': expr
Hstep: rtc step (App v2 v1) e'
Hval: value_ok e' trtc step (Rec (nat_to_expr n) (App v2 v1) v2) ?e'eauto. Defined.n: nat
v2: expr
t: ty
Hv2: value_ok v2 (Fun t t)
IHn: forall v1 : expr, value_ok v1 t -> expr_ok (Rec (nat_to_expr n) v1 v2) t
v1: expr
Hv1: value_ok v1 t
e': expr
Hstep: rtc step (App v2 v1) e'
Hval: value_ok e' texpr_ok (Rec (nat_to_expr n) e' v2) tv: expr
t: tyvalue_ok v t -> closed vv: expr
t: tyvalue_ok v t -> closed vv: expr
t: ty
H: value_ok v tclosed vv: expr
H: exists n : nat, v = nat_to_expr nclosed vv: expr
t1, t2: ty
H: closed v /\ (exists (x : string) (ebody : expr), v = Lam x ebody /\ (forall v : expr, value_ok v t1 -> exists e' : expr, rtc step (subst x v ebody) e' /\ value_ok e' t2))closed vv: expr
H: exists n : nat, v = nat_to_expr nclosed vn: natclosed (nat_to_expr n)n: nat
x: string
v: exprsubst x v (nat_to_expr n) = nat_to_expr nn: nat
x: string
v: expr
IHn: subst x v (nat_to_expr n) = nat_to_expr nSucc (subst x v (nat_to_expr n)) = Succ (nat_to_expr n)auto.n: nat
x: string
v: expr
IHn: subst x v (nat_to_expr n) = nat_to_expr nSucc (nat_to_expr n) = Succ (nat_to_expr n)v: expr
t1, t2: ty
H: closed v /\ (exists (x : string) (ebody : expr), v = Lam x ebody /\ (forall v : expr, value_ok v t1 -> exists e' : expr, rtc step (subst x v ebody) e' /\ value_ok e' t2))closed vauto. Defined. (* Environments and multi-substitutions *) Definition env := string -> option expr. Fixpoint subst_map (env : env) (e : expr) : expr := match e with | Var x => match env x with | Some v => v | None => e end | Lam x e => Lam x (subst_map (delete x env) e) | App e1 e2 => App (subst_map env e1) (subst_map env e2) | Zero => Zero | Succ e => Succ (subst_map env e) | Rec e1 e2 e3 => Rec (subst_map env e1) (subst_map env e2) (subst_map env e3) end.v: expr
t1, t2: ty
H: closed v
H0: exists (x : string) (ebody : expr), v = Lam x ebody /\ (forall v : expr, value_ok v t1 -> exists e' : expr, rtc step (subst x v ebody) e' /\ value_ok e' t2)closed venv1, env2: string -> option expr
e: exprenv1 == env2 -> subst_map env1 e = subst_map env2 eenv1, env2: string -> option expr
e: exprenv1 == env2 -> subst_map env1 e = subst_map env2 ee: exprforall env1 env2 : string -> option expr, env1 == env2 -> subst_map env1 e = subst_map env2 ex: string
env1, env2: string -> option expr
H: env1 == env2match env1 x with | Some v => v | None => Var x end = match env2 x with | Some v => v | None => Var x endx: string
e: expr
IHe: forall env1 env2 : string -> option expr, env1 == env2 -> subst_map env1 e = subst_map env2 e
env1, env2: string -> option expr
H: env1 == env2subst_map (delete x env1) e = subst_map (delete x env2) ex: string
env1, env2: string -> option expr
H: env1 == env2match env1 x with | Some v => v | None => Var x end = match env2 x with | Some v => v | None => Var x endauto.x: string
env1, env2: string -> option expr
H: env1 == env2match env2 x with | Some v => v | None => Var x end = match env2 x with | Some v => v | None => Var x endx: string
e: expr
IHe: forall env1 env2 : string -> option expr, env1 == env2 -> subst_map env1 e = subst_map env2 e
env1, env2: string -> option expr
H: env1 == env2subst_map (delete x env1) e = subst_map (delete x env2) esimpfun. Defined.x: string
e: expr
IHe: forall env1 env2 : string -> option expr, env1 == env2 -> subst_map env1 e = subst_map env2 e
env1, env2: string -> option expr
H: env1 == env2delete x env1 == delete x env2e: exprsubst_map empty e = ee: exprsubst_map empty e = ex: string
e: expr
IHe: subst_map empty e = eLam x (subst_map (delete x empty) e) = Lam x ex: string
e: expr
IHe: subst_map empty e = esubst_map (delete x empty) e = eerewrite subst_map_eq; eauto. Defined.x: string
e: expr
IHe: subst_map empty e = e
H: delete x empty == (empty : env)subst_map (delete x empty) e = eGamma: ctx
env: string -> option expr
e: expr
x: string
v: expr
t: tytyped Gamma e t -> (forall (x : string) (v : expr), env x = Some v -> closed v) -> Gamma x = None \/ env x <> None -> subst x v (subst_map env e) = subst_map env eGamma: ctx
env: string -> option expr
e: expr
x: string
v: expr
t: tytyped Gamma e t -> (forall (x : string) (v : expr), env x = Some v -> closed v) -> Gamma x = None \/ env x <> None -> subst x v (subst_map env e) = subst_map env eGamma: ctx
env: string -> option expr
e: expr
x: string
v: expr
t: ty
H: typed Gamma e t(forall (x : string) (v : expr), env x = Some v -> closed v) -> Gamma x = None \/ env x <> None -> subst x v (subst_map env e) = subst_map env eGamma: ctx
e: expr
x: string
v: expr
t: ty
H: typed Gamma e tforall env : string -> option expr, (forall (x : string) (v : expr), env x = Some v -> closed v) -> Gamma x = None \/ env x <> None -> subst x v (subst_map env e) = subst_map env ex: string
v: expr
x0: string
t: ty
Gamma: ctx
H: Gamma x0 = Some t
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: Gamma x = None \/ env0 x <> Nonesubst x v match env0 x0 with | Some v => v | None => Var x0 end = match env0 x0 with | Some v => v | None => Var x0 endx: string
v: expr
x0: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (insert x0 t1 Gamma) e t2
IHtyped: forall env : string -> option expr, (forall (x : string) (v : expr), env x = Some v -> closed v) -> insert x0 t1 Gamma x = None \/ env x <> None -> subst x v (subst_map env e) = subst_map env e
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: Gamma x = None \/ env0 x <> NoneLam x0 (if string_dec x x0 then subst_map (delete x0 env0) e else subst x v (subst_map (delete x0 env0) e)) = Lam x0 (subst_map (delete x0 env0) e)x: string
v: expr
x0: string
t: ty
Gamma: ctx
H: Gamma x0 = Some t
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: Gamma x = None \/ env0 x <> Nonesubst x v match env0 x0 with | Some v => v | None => Var x0 end = match env0 x0 with | Some v => v | None => Var x0 endx: string
v: expr
x0: string
t: ty
Gamma: ctx
H: Gamma x0 = Some t
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: Gamma x = None \/ env0 x <> None
e: expr
E: env0 x0 = Some esubst x v e = ex: string
v: expr
x0: string
t: ty
Gamma: ctx
H: Gamma x0 = Some t
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: Gamma x = None \/ env0 x <> None
E: env0 x0 = Nonesubst x v (Var x0) = Var x0x: string
v: expr
x0: string
t: ty
Gamma: ctx
H: Gamma x0 = Some t
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: Gamma x = None \/ env0 x <> None
e: expr
E: env0 x0 = Some esubst x v e = eeauto.x: string
v: expr
x0: string
t: ty
Gamma: ctx
H: Gamma x0 = Some t
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: Gamma x = None \/ env0 x <> None
e: expr
E: env0 x0 = Some eenv0 ?x = Some ex: string
v: expr
x0: string
t: ty
Gamma: ctx
H: Gamma x0 = Some t
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: Gamma x = None \/ env0 x <> None
E: env0 x0 = Nonesubst x v (Var x0) = Var x0x: string
v: expr
x0: string
t: ty
Gamma: ctx
H: Gamma x0 = Some t
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: Gamma x = None \/ env0 x <> None
E: env0 x0 = None(if string_dec x x0 then v else Var x0) = Var x0destruct H1; simpeq.v: expr
x0: string
t: ty
Gamma: ctx
H: Gamma x0 = Some t
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: Gamma x0 = None \/ env0 x0 <> None
E: env0 x0 = Nonev = Var x0x: string
v: expr
x0: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (insert x0 t1 Gamma) e t2
IHtyped: forall env : string -> option expr, (forall (x : string) (v : expr), env x = Some v -> closed v) -> insert x0 t1 Gamma x = None \/ env x <> None -> subst x v (subst_map env e) = subst_map env e
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: Gamma x = None \/ env0 x <> NoneLam x0 (if string_dec x x0 then subst_map (delete x0 env0) e else subst x v (subst_map (delete x0 env0) e)) = Lam x0 (subst_map (delete x0 env0) e)x: string
v: expr
x0: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (insert x0 t1 Gamma) e t2
IHtyped: forall env : string -> option expr, (forall (x : string) (v : expr), env x = Some v -> closed v) -> insert x0 t1 Gamma x = None \/ env x <> None -> subst x v (subst_map env e) = subst_map env e
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: Gamma x = None \/ env0 x <> None
n: x <> x0Lam x0 (subst x v (subst_map (delete x0 env0) e)) = Lam x0 (subst_map (delete x0 env0) e)eapply IHtyped; simpfun. Defined.x: string
v: expr
x0: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (insert x0 t1 Gamma) e t2
IHtyped: forall env : string -> option expr, (forall (x : string) (v : expr), env x = Some v -> closed v) -> insert x0 t1 Gamma x = None \/ env x <> None -> subst x v (subst_map env e) = subst_map env e
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: Gamma x = None \/ env0 x <> None
n: x <> x0subst x v (subst_map (delete x0 env0) e) = subst_map (delete x0 env0) eGamma: ctx
env: string -> option expr
e: expr
x: string
v: expr
t: tytyped Gamma e t -> (forall (x : string) (v : expr), env x = Some v -> closed v) -> env x = None -> subst x v (subst_map env e) = subst_map (insert x v env) eGamma: ctx
env: string -> option expr
e: expr
x: string
v: expr
t: tytyped Gamma e t -> (forall (x : string) (v : expr), env x = Some v -> closed v) -> env x = None -> subst x v (subst_map env e) = subst_map (insert x v env) eGamma: ctx
env: string -> option expr
e: expr
x: string
v: expr
t: ty
H: typed Gamma e t(forall (x : string) (v : expr), env x = Some v -> closed v) -> env x = None -> subst x v (subst_map env e) = subst_map (insert x v env) eGamma: ctx
e: expr
x: string
v: expr
t: ty
H: typed Gamma e tforall env : string -> option expr, (forall (x : string) (v : expr), env x = Some v -> closed v) -> env x = None -> subst x v (subst_map env e) = subst_map (insert x v env) ex: string
v: expr
x0: string
t: ty
Gamma: ctx
H: Gamma x0 = Some t
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x = Nonesubst x v match env0 x0 with | Some v => v | None => Var x0 end = match insert x v env0 x0 with | Some v => v | None => Var x0 endx: string
v: expr
x0: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (insert x0 t1 Gamma) e t2
IHtyped: forall env : string -> option expr, (forall (x : string) (v : expr), env x = Some v -> closed v) -> env x = None -> subst x v (subst_map env e) = subst_map (insert x v env) e
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x = NoneLam x0 (if string_dec x x0 then subst_map (delete x0 env0) e else subst x v (subst_map (delete x0 env0) e)) = Lam x0 (subst_map (delete x0 (insert x v env0)) e)x: string
v: expr
x0: string
t: ty
Gamma: ctx
H: Gamma x0 = Some t
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x = Nonesubst x v match env0 x0 with | Some v => v | None => Var x0 end = match insert x v env0 x0 with | Some v => v | None => Var x0 endx: string
v: expr
x0: string
t: ty
Gamma: ctx
H: Gamma x0 = Some t
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x = Nonesubst x v match env0 x0 with | Some v => v | None => Var x0 end = match (if string_dec x x0 then Some v else env0 x0) with | Some v => v | None => Var x0 endv: expr
x0: string
t: ty
Gamma: ctx
H: Gamma x0 = Some t
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x0 = Nonesubst x0 v match env0 x0 with | Some v => v | None => Var x0 end = vx: string
v: expr
x0: string
t: ty
Gamma: ctx
H: Gamma x0 = Some t
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x = None
n: x <> x0subst x v match env0 x0 with | Some v => v | None => Var x0 end = match env0 x0 with | Some v => v | None => Var x0 endv: expr
x0: string
t: ty
Gamma: ctx
H: Gamma x0 = Some t
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x0 = Nonesubst x0 v match env0 x0 with | Some v => v | None => Var x0 end = vv: expr
x0: string
t: ty
Gamma: ctx
H: Gamma x0 = Some t
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x0 = Nonesubst x0 v (Var x0) = vdestruct string_dec; simpeq.v: expr
x0: string
t: ty
Gamma: ctx
H: Gamma x0 = Some t
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x0 = None(if string_dec x0 x0 then v else Var x0) = vx: string
v: expr
x0: string
t: ty
Gamma: ctx
H: Gamma x0 = Some t
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x = None
n: x <> x0subst x v match env0 x0 with | Some v => v | None => Var x0 end = match env0 x0 with | Some v => v | None => Var x0 endx: string
v: expr
x0: string
t: ty
Gamma: ctx
H: Gamma x0 = Some t
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x = None
n: x <> x0
e: expr
E: env0 x0 = Some esubst x v e = eeauto.x: string
v: expr
x0: string
t: ty
Gamma: ctx
H: Gamma x0 = Some t
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x = None
n: x <> x0
e: expr
E: env0 x0 = Some eenv0 ?x = Some ex: string
v: expr
x0: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (insert x0 t1 Gamma) e t2
IHtyped: forall env : string -> option expr, (forall (x : string) (v : expr), env x = Some v -> closed v) -> env x = None -> subst x v (subst_map env e) = subst_map (insert x v env) e
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x = NoneLam x0 (if string_dec x x0 then subst_map (delete x0 env0) e else subst x v (subst_map (delete x0 env0) e)) = Lam x0 (subst_map (delete x0 (insert x v env0)) e)x: string
v: expr
x0: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (insert x0 t1 Gamma) e t2
IHtyped: forall env : string -> option expr, (forall (x : string) (v : expr), env x = Some v -> closed v) -> env x = None -> subst x v (subst_map env e) = subst_map (insert x v env) e
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x = None(if string_dec x x0 then subst_map (delete x0 env0) e else subst x v (subst_map (delete x0 env0) e)) = subst_map (delete x0 (insert x v env0)) ev: expr
x0: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (fun x' : string => if string_dec x0 x' then Some t1 else Gamma x') e t2
IHtyped: forall env : string -> option expr, (forall (x : string) (v : expr), env x = Some v -> closed v) -> env x0 = None -> subst x0 v (subst_map env e) = subst_map (fun x' : string => if string_dec x0 x' then Some v else env x') e
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x0 = Nonesubst_map (fun x' : string => if string_dec x0 x' then None else env0 x') e = subst_map (fun x' : string => if string_dec x0 x' then None else if string_dec x0 x' then Some v else env0 x') ex: string
v: expr
x0: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (fun x' : string => if string_dec x0 x' then Some t1 else Gamma x') e t2
IHtyped: forall env : string -> option expr, (forall (x : string) (v : expr), env x = Some v -> closed v) -> env x = None -> subst x v (subst_map env e) = subst_map (fun x' : string => if string_dec x x' then Some v else env x') e
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x = None
n: x <> x0subst x v (subst_map (fun x' : string => if string_dec x0 x' then None else env0 x') e) = subst_map (fun x' : string => if string_dec x0 x' then None else if string_dec x x' then Some v else env0 x') ev: expr
x0: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (fun x' : string => if string_dec x0 x' then Some t1 else Gamma x') e t2
IHtyped: forall env : string -> option expr, (forall (x : string) (v : expr), env x = Some v -> closed v) -> env x0 = None -> subst x0 v (subst_map env e) = subst_map (fun x' : string => if string_dec x0 x' then Some v else env x') e
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x0 = Nonesubst_map (fun x' : string => if string_dec x0 x' then None else env0 x') e = subst_map (fun x' : string => if string_dec x0 x' then None else if string_dec x0 x' then Some v else env0 x') esimpfun.v: expr
x0: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (fun x' : string => if string_dec x0 x' then Some t1 else Gamma x') e t2
IHtyped: forall env : string -> option expr, (forall (x : string) (v : expr), env x = Some v -> closed v) -> env x0 = None -> subst x0 v (subst_map env e) = subst_map (fun x' : string => if string_dec x0 x' then Some v else env x') e
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x0 = None(fun x' : string => if string_dec x0 x' then None else env0 x') == (fun x' : string => if string_dec x0 x' then None else if string_dec x0 x' then Some v else env0 x')x: string
v: expr
x0: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (fun x' : string => if string_dec x0 x' then Some t1 else Gamma x') e t2
IHtyped: forall env : string -> option expr, (forall (x : string) (v : expr), env x = Some v -> closed v) -> env x = None -> subst x v (subst_map env e) = subst_map (fun x' : string => if string_dec x x' then Some v else env x') e
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x = None
n: x <> x0subst x v (subst_map (fun x' : string => if string_dec x0 x' then None else env0 x') e) = subst_map (fun x' : string => if string_dec x0 x' then None else if string_dec x x' then Some v else env0 x') ex: string
v: expr
x0: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (fun x' : string => if string_dec x0 x' then Some t1 else Gamma x') e t2
IHtyped: forall env : string -> option expr, (forall (x : string) (v : expr), env x = Some v -> closed v) -> env x = None -> subst x v (subst_map env e) = subst_map (fun x' : string => if string_dec x x' then Some v else env x') e
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x = None
n: x <> x0subst_map (fun x' : string => if string_dec x x' then Some v else if string_dec x0 x' then None else env0 x') e = subst_map (fun x' : string => if string_dec x0 x' then None else if string_dec x x' then Some v else env0 x') ex: string
v: expr
x0: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (fun x' : string => if string_dec x0 x' then Some t1 else Gamma x') e t2
IHtyped: forall env : string -> option expr, (forall (x : string) (v : expr), env x = Some v -> closed v) -> env x = None -> subst x v (subst_map env e) = subst_map (fun x' : string => if string_dec x x' then Some v else env x') e
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x = None
n: x <> x0forall (x : string) (v : expr), (if string_dec x0 x then None else env0 x) = Some v -> closed vx: string
v: expr
x0: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (fun x' : string => if string_dec x0 x' then Some t1 else Gamma x') e t2
IHtyped: forall env : string -> option expr, (forall (x : string) (v : expr), env x = Some v -> closed v) -> env x = None -> subst x v (subst_map env e) = subst_map (fun x' : string => if string_dec x x' then Some v else env x') e
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x = None
n: x <> x0(if string_dec x0 x then None else env0 x) = Nonex: string
v: expr
x0: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (fun x' : string => if string_dec x0 x' then Some t1 else Gamma x') e t2
IHtyped: forall env : string -> option expr, (forall (x : string) (v : expr), env x = Some v -> closed v) -> env x = None -> subst x v (subst_map env e) = subst_map (fun x' : string => if string_dec x x' then Some v else env x') e
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x = None
n: x <> x0subst_map (fun x' : string => if string_dec x x' then Some v else if string_dec x0 x' then None else env0 x') e = subst_map (fun x' : string => if string_dec x0 x' then None else if string_dec x x' then Some v else env0 x') esimpfun.x: string
v: expr
x0: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (fun x' : string => if string_dec x0 x' then Some t1 else Gamma x') e t2
IHtyped: forall env : string -> option expr, (forall (x : string) (v : expr), env x = Some v -> closed v) -> env x = None -> subst x v (subst_map env e) = subst_map (fun x' : string => if string_dec x x' then Some v else env x') e
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x = None
n: x <> x0(fun x' : string => if string_dec x x' then Some v else if string_dec x0 x' then None else env0 x') == (fun x' : string => if string_dec x0 x' then None else if string_dec x x' then Some v else env0 x')simpfun.x: string
v: expr
x0: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (fun x' : string => if string_dec x0 x' then Some t1 else Gamma x') e t2
IHtyped: forall env : string -> option expr, (forall (x : string) (v : expr), env x = Some v -> closed v) -> env x = None -> subst x v (subst_map env e) = subst_map (fun x' : string => if string_dec x x' then Some v else env x') e
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x = None
n: x <> x0forall (x : string) (v : expr), (if string_dec x0 x then None else env0 x) = Some v -> closed vsimpfun. Defined. (* Lemmas about environments *) Definition env_ok (env : env) (Gamma : ctx) := forall x, match Gamma x, env x with | Some t, Some v => value_ok v t | None, None => True | _, _ => False end.x: string
v: expr
x0: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (fun x' : string => if string_dec x0 x' then Some t1 else Gamma x') e t2
IHtyped: forall env : string -> option expr, (forall (x : string) (v : expr), env x = Some v -> closed v) -> env x = None -> subst x v (subst_map env e) = subst_map (fun x' : string => if string_dec x x' then Some v else env x') e
env0: string -> option expr
H0: forall (x : string) (v : expr), env0 x = Some v -> closed v
H1: env0 x = None
n: x <> x0(if string_dec x0 x then None else env0 x) = Nonex: string
v: expr
t: ty
env: lec12_termination.env
Gamma: ctxenv_ok env Gamma -> value_ok v t -> env_ok (insert x v env) (insert x t Gamma)x: string
v: expr
t: ty
env: lec12_termination.env
Gamma: ctxenv_ok env Gamma -> value_ok v t -> env_ok (insert x v env) (insert x t Gamma)x: string
v: expr
t: ty
env: lec12_termination.env
Gamma: ctx
Henv: env_ok env Gamma
Hval: value_ok v t
x': stringmatch insert x t Gamma x' with | Some t => match insert x v env x' with | Some v => value_ok v t | None => False end | None => match insert x v env x' with | Some _ => False | None => True end endx: string
v: expr
t: ty
env: lec12_termination.env
Gamma: ctx
Henv: env_ok env Gamma
Hval: value_ok v t
x': stringmatch (if string_dec x x' then Some t else Gamma x') with | Some t => match (if string_dec x x' then Some v else env x') with | Some v => value_ok v t | None => False end | None => match (if string_dec x x' then Some v else env x') with | Some _ => False | None => True end endapply Henv. Defined.x: string
v: expr
t: ty
env: lec12_termination.env
Gamma: ctx
Henv: env_ok env Gamma
Hval: value_ok v t
x': string
n: x <> x'match Gamma x' with | Some t => match env x' with | Some v => value_ok v t | None => False end | None => match env x' with | Some _ => False | None => True end endGamma: ctx
env1, env2: string -> option exprenv2 == env1 -> env_ok env1 Gamma -> env_ok env2 GammaGamma: ctx
env1, env2: string -> option exprenv2 == env1 -> env_ok env1 Gamma -> env_ok env2 GammaGamma: ctx
env1, env2: string -> option expr
H12: env2 == env1
H1: env_ok env1 Gamma
x: stringmatch Gamma x with | Some t => match env2 x with | Some v => value_ok v t | None => False end | None => match env2 x with | Some _ => False | None => True end endGamma: ctx
env1, env2: string -> option expr
H12: forall x : string, env2 x = env1 x
H1: forall x : string, match Gamma x with | Some t => match env1 x with | Some v => value_ok v t | None => False end | None => match env1 x with | Some _ => False | None => True end end
x: stringmatch Gamma x with | Some t => match env2 x with | Some v => value_ok v t | None => False end | None => match env2 x with | Some _ => False | None => True end endGamma: ctx
env1, env2: string -> option expr
H12: forall x : string, env2 x = env1 x
x: string
H1: match Gamma x with | Some t => match env1 x with | Some v => value_ok v t | None => False end | None => match env1 x with | Some _ => False | None => True end endmatch Gamma x with | Some t => match env2 x with | Some v => value_ok v t | None => False end | None => match env2 x with | Some _ => False | None => True end endeauto. Defined.Gamma: ctx
env1, env2: string -> option expr
H12: forall x : string, env2 x = env1 x
x: string
H1: match Gamma x with | Some t => match env2 x with | Some v => value_ok v t | None => False end | None => match env2 x with | Some _ => False | None => True end endmatch Gamma x with | Some t => match env2 x with | Some v => value_ok v t | None => False end | None => match env2 x with | Some _ => False | None => True end endGamma: ctx
env: lec12_termination.env
e: expr
t: tytyped Gamma e t -> env_ok env Gamma -> closed (subst_map env e)Gamma: ctx
env: lec12_termination.env
e: expr
t: tytyped Gamma e t -> env_ok env Gamma -> closed (subst_map env e)Gamma: ctx
env: lec12_termination.env
e: expr
t: ty
H: typed Gamma e t
H0: env_ok env Gamma
x: string
v: exprsubst x v (subst_map env e) = subst_map env eGamma: ctx
env: lec12_termination.env
e: expr
t: ty
H: typed Gamma e t
H0: env_ok env Gamma
x: string
v: exprforall (x : string) (v : expr), env x = Some v -> closed vGamma: ctx
env: lec12_termination.env
e: expr
t: ty
H: typed Gamma e t
H0: env_ok env Gamma
x: string
v: exprGamma x = None \/ env x <> NoneGamma: ctx
env: lec12_termination.env
e: expr
t: ty
H: typed Gamma e t
H0: env_ok env Gamma
x: string
v: exprforall (x : string) (v : expr), env x = Some v -> closed vGamma: ctx
env: lec12_termination.env
e: expr
t: ty
H: typed Gamma e t
H0: env_ok env Gamma
x: string
v: expr
x0: string
v0: expr
H1: env x0 = Some v0closed v0Gamma: ctx
env: lec12_termination.env
e: expr
t: ty
H: typed Gamma e t
H0: forall x : string, match Gamma x with | Some t => match env x with | Some v => value_ok v t | None => False end | None => match env x with | Some _ => False | None => True end end
x: string
v: expr
x0: string
v0: expr
H1: env x0 = Some v0closed v0Gamma: ctx
env: lec12_termination.env
e: expr
t: ty
H: typed Gamma e t
x0: string
H0: match Gamma x0 with | Some t => match env x0 with | Some v => value_ok v t | None => False end | None => match env x0 with | Some _ => False | None => True end end
x: string
v, v0: expr
H1: env x0 = Some v0closed v0Gamma: ctx
env: lec12_termination.env
e: expr
t: ty
H: typed Gamma e t
x0: string
v0: expr
H0: match Gamma x0 with | Some t => value_ok v0 t | None => False end
x: string
v: expr
H1: env x0 = Some v0closed v0destruct H0.Gamma: ctx
env: lec12_termination.env
e: expr
t: ty
H: typed Gamma e t
x0: string
v0: expr
H0: False
x: string
v: expr
H1: env x0 = Some v0closed v0Gamma: ctx
env: lec12_termination.env
e: expr
t: ty
H: typed Gamma e t
H0: env_ok env Gamma
x: string
v: exprGamma x = None \/ env x <> NoneGamma: ctx
env: lec12_termination.env
e: expr
t: ty
H: typed Gamma e t
H0: forall x : string, match Gamma x with | Some t => match env x with | Some v => value_ok v t | None => False end | None => match env x with | Some _ => False | None => True end end
x: string
v: exprGamma x = None \/ env x <> NoneGamma: ctx
env: lec12_termination.env
e: expr
t: ty
H: typed Gamma e t
H0: forall x : string, match Gamma x with | Some t => match env x with | Some v => value_ok v t | None => False end | None => match env x with | Some _ => False | None => True end end
x: string
v: expr
t0: ty
E: Gamma x = Some t0Some t0 = None \/ env x <> NoneGamma: ctx
env: lec12_termination.env
e: expr
t: ty
H: typed Gamma e t
H0: forall x : string, match Gamma x with | Some t => match env x with | Some v => value_ok v t | None => False end | None => match env x with | Some _ => False | None => True end end
x: string
v: expr
t0: ty
E: Gamma x = Some t0
e0: expr
E': env x = Some e0Some t0 = None \/ Some e0 <> NoneGamma: ctx
env: lec12_termination.env
e: expr
t: ty
H: typed Gamma e t
H0: forall x : string, match Gamma x with | Some t => match env x with | Some v => value_ok v t | None => False end | None => match env x with | Some _ => False | None => True end end
x: string
v: expr
t0: ty
E: Gamma x = Some t0
E': env x = NoneSome t0 = None \/ None <> NoneGamma: ctx
env: lec12_termination.env
e: expr
t: ty
H: typed Gamma e t
H0: forall x : string, match Gamma x with | Some t => match env x with | Some v => value_ok v t | None => False end | None => match env x with | Some _ => False | None => True end end
x: string
v: expr
t0: ty
E: Gamma x = Some t0
e0: expr
E': env x = Some e0Some t0 = None \/ Some e0 <> NoneGamma: ctx
env: lec12_termination.env
e: expr
t: ty
H: typed Gamma e t
H0: forall x : string, match Gamma x with | Some t => match env x with | Some v => value_ok v t | None => False end | None => match env x with | Some _ => False | None => True end end
x: string
v: expr
t0: ty
E: Gamma x = Some t0
e0: expr
E': env x = Some e0Some e0 <> Nonesimpeq.Gamma: ctx
env: lec12_termination.env
e: expr
t: ty
H: typed Gamma e t
H0: forall x : string, match Gamma x with | Some t => match env x with | Some v => value_ok v t | None => False end | None => match env x with | Some _ => False | None => True end end
x: string
v: expr
t0: ty
E: Gamma x = Some t0
e0: expr
E': env x = Some e0
H1: Some e0 = NoneFalseGamma: ctx
env: lec12_termination.env
e: expr
t: ty
H: typed Gamma e t
H0: forall x : string, match Gamma x with | Some t => match env x with | Some v => value_ok v t | None => False end | None => match env x with | Some _ => False | None => True end end
x: string
v: expr
t0: ty
E: Gamma x = Some t0
E': env x = NoneSome t0 = None \/ None <> NoneGamma: ctx
env: lec12_termination.env
e: expr
t: ty
H: typed Gamma e t
x: string
H0: match Gamma x with | Some t => match env x with | Some v => value_ok v t | None => False end | None => match env x with | Some _ => False | None => True end end
v: expr
t0: ty
E: Gamma x = Some t0
E': env x = NoneSome t0 = None \/ None <> NoneGamma: ctx
env: lec12_termination.env
e: expr
t: ty
H: typed Gamma e t
x: string
t0: ty
H0: match env x with | Some v => value_ok v t0 | None => False end
v: expr
E: Gamma x = Some t0
E': env x = NoneSome t0 = None \/ None <> Nonedestruct H0. Defined. (* Generalized termination proof *)Gamma: ctx
env: lec12_termination.env
e: expr
t: ty
H: typed Gamma e t
x: string
t0: ty
H0: False
v: expr
E: Gamma x = Some t0
E': env x = NoneSome t0 = None \/ None <> NoneGamma: ctx
env: lec12_termination.env
e: expr
t: tytyped Gamma e t -> env_ok env Gamma -> expr_ok (subst_map env e) tGamma: ctx
env: lec12_termination.env
e: expr
t: tytyped Gamma e t -> env_ok env Gamma -> expr_ok (subst_map env e) tGamma: ctx
env: lec12_termination.env
e: expr
t: ty
Htyped: typed Gamma e tenv_ok env Gamma -> expr_ok (subst_map env e) tGamma: ctx
e: expr
t: ty
Htyped: typed Gamma e tforall env : env, env_ok env Gamma -> expr_ok (subst_map env e) tx: string
t: ty
Gamma: ctx
H: Gamma x = Some t
env: lec12_termination.env
Henv: env_ok env Gammaexpr_ok (subst_map env (Var x)) tx: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: env_ok env Gammaexpr_ok (subst_map env (Lam x e)) (Fun t1 t2)e1, e2: expr
t1, t2: ty
Gamma: ctx
Htyped1: typed Gamma e1 (Fun t1 t2)
Htyped2: typed Gamma e2 t1
IHHtyped1: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e1) (Fun t1 t2)
IHHtyped2: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e2) t1
env: lec12_termination.env
Henv: env_ok env Gammaexpr_ok (subst_map env (App e1 e2)) t2Gamma: ctx
env: lec12_termination.env
Henv: env_ok env Gammaexpr_ok (subst_map env Zero) Nate: expr
Gamma: ctx
Htyped: typed Gamma e Nat
IHHtyped: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e) Nat
env: lec12_termination.env
Henv: env_ok env Gammaexpr_ok (subst_map env (Succ e)) Nate1, e2, e3: expr
Gamma: ctx
t: ty
Htyped1: typed Gamma e1 Nat
Htyped2: typed Gamma e2 t
Htyped3: typed Gamma e3 (Fun t t)
IHHtyped1: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e1) Nat
IHHtyped2: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e2) t
IHHtyped3: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e3) (Fun t t)
env: lec12_termination.env
Henv: env_ok env Gammaexpr_ok (subst_map env (Rec e1 e2 e3)) tx: string
t: ty
Gamma: ctx
H: Gamma x = Some t
env: lec12_termination.env
Henv: env_ok env Gammaexpr_ok (subst_map env (Var x)) tx: string
t: ty
Gamma: ctx
H: Gamma x = Some t
env: lec12_termination.env
Henv: forall x : string, match Gamma x with | Some t => match env x with | Some v => value_ok v t | None => False end | None => match env x with | Some _ => False | None => True end endexpr_ok (subst_map env (Var x)) tx: string
t: ty
Gamma: ctx
H: Gamma x = Some t
env: lec12_termination.env
Henv: forall x : string, match Gamma x with | Some t => match env x with | Some v => value_ok v t | None => False end | None => match env x with | Some _ => False | None => True end endexpr_ok match env x with | Some v => v | None => Var x end tx: string
t: ty
Gamma: ctx
H: Gamma x = Some t
env: lec12_termination.env
Henv: match Gamma x with | Some t => match env x with | Some v => value_ok v t | None => False end | None => match env x with | Some _ => False | None => True end endexpr_ok match env x with | Some v => v | None => Var x end tx: string
t: ty
Gamma: ctx
H: Gamma x = Some t
env: lec12_termination.env
Henv: match env x with | Some v => value_ok v t | None => False endexpr_ok match env x with | Some v => v | None => Var x end tx: string
t: ty
Gamma: ctx
H: Gamma x = Some t
env: lec12_termination.env
e: expr
Henv: value_ok e texpr_ok e tx: string
t: ty
Gamma: ctx
H: Gamma x = Some t
env: lec12_termination.env
Henv: Falseexpr_ok (Var x) tx: string
t: ty
Gamma: ctx
H: Gamma x = Some t
env: lec12_termination.env
e: expr
Henv: value_ok e texpr_ok e tauto.x: string
t: ty
Gamma: ctx
H: Gamma x = Some t
env: lec12_termination.env
e: expr
Henv: value_ok e tvalue_ok e tdestruct Henv.x: string
t: ty
Gamma: ctx
H: Gamma x = Some t
env: lec12_termination.env
Henv: Falseexpr_ok (Var x) tx: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: env_ok env Gammaexpr_ok (subst_map env (Lam x e)) (Fun t1 t2)x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: env_ok env Gammavalue_ok (subst_map env (Lam x e)) (Fun t1 t2)x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: env_ok env Gammaclosed (subst_map env (Lam x e))x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: env_ok env Gammaexists (x0 : string) (ebody : expr), subst_map env (Lam x e) = Lam x0 ebody /\ (forall v : expr, value_ok v t1 -> exists e' : expr, rtc step (subst x0 v ebody) e' /\ value_ok e' t2)eapply env_ok_closed; eauto using typed.x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: env_ok env Gammaclosed (subst_map env (Lam x e))x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: env_ok env Gammaexists (x0 : string) (ebody : expr), subst_map env (Lam x e) = Lam x0 ebody /\ (forall v : expr, value_ok v t1 -> exists e' : expr, rtc step (subst x0 v ebody) e' /\ value_ok e' t2)x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: env_ok env Gammasubst_map env (Lam x e) = Lam ?Goal3 ?Goal4 /\ (forall v : expr, value_ok v t1 -> exists e' : expr, rtc step (subst ?Goal3 v ?Goal4) e' /\ value_ok e' t2)x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: env_ok env GammaLam x (subst_map (delete x env) e) = Lam ?Goal3 ?Goal4 /\ (forall v : expr, value_ok v t1 -> exists e' : expr, rtc step (subst ?Goal3 v ?Goal4) e' /\ value_ok e' t2)x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: env_ok env Gammaforall v : expr, value_ok v t1 -> exists e' : expr, rtc step (subst x v (subst_map (delete x env) e)) e' /\ value_ok e' t2x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: env_ok env Gamma
v: expr
Hv: value_ok v t1exists e' : expr, rtc step (subst x v (subst_map (delete x env) e)) e' /\ value_ok e' t2x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: env_ok env Gamma
v: expr
Hv: value_ok v t1exists e' : expr, rtc step (subst_map (insert x v (delete x env)) e) e' /\ value_ok e' t2x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: env_ok env Gamma
v: expr
Hv: value_ok v t1forall (x0 : string) (v : expr), delete x env x0 = Some v -> closed vx: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: env_ok env Gamma
v: expr
Hv: value_ok v t1delete x env x = Nonex: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: env_ok env Gamma
v: expr
Hv: value_ok v t1exists e' : expr, rtc step (subst_map (insert x v (delete x env)) e) e' /\ value_ok e' t2x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: env_ok env Gamma
v: expr
Hv: value_ok v t1env_ok (insert x v (delete x env)) (insert x t1 Gamma)x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: env_ok env Gamma
v: expr
Hv: value_ok v t1
Hinsert: insert x v (delete x env) == insert x v envenv_ok (insert x v (delete x env)) (insert x t1 Gamma)apply env_ok_insert; auto.x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: env_ok env Gamma
v: expr
Hv: value_ok v t1
Hinsert: insert x v (delete x env) == insert x v envenv_ok (insert x v env) (insert x t1 Gamma)x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: env_ok env Gamma
v: expr
Hv: value_ok v t1forall (x0 : string) (v : expr), delete x env x0 = Some v -> closed vx: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: env_ok env Gamma
v: expr
Hv: value_ok v t1
x0: string
v0: expr
H: delete x env x0 = Some v0closed v0x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: forall x : string, match Gamma x with | Some t => match env x with | Some v => value_ok v t | None => False end | None => match env x with | Some _ => False | None => True end end
v: expr
Hv: value_ok v t1
x0: string
v0: expr
H: delete x env x0 = Some v0closed v0x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: forall x : string, match Gamma x with | Some t => match env x with | Some v => value_ok v t | None => False end | None => match env x with | Some _ => False | None => True end end
v: expr
Hv: value_ok v t1
x0: string
v0: expr
H: (if string_dec x x0 then None else env x0) = Some v0closed v0x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: forall x : string, match Gamma x with | Some t => match env x with | Some v => value_ok v t | None => False end | None => match env x with | Some _ => False | None => True end end
v: expr
Hv: value_ok v t1
x0: string
v0: expr
n: x <> x0
H: env x0 = Some v0closed v0x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
x0: string
Henv: match Gamma x0 with | Some t => match env x0 with | Some v => value_ok v t | None => False end | None => match env x0 with | Some _ => False | None => True end end
v: expr
Hv: value_ok v t1
v0: expr
n: x <> x0
H: env x0 = Some v0closed v0x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
x0: string
v0: expr
Henv: match Gamma x0 with | Some t => value_ok v0 t | None => False end
v: expr
Hv: value_ok v t1
n: x <> x0
H: env x0 = Some v0closed v0x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
x0: string
v0: expr
t: ty
Henv: value_ok v0 t
v: expr
Hv: value_ok v t1
n: x <> x0
H: env x0 = Some v0closed v0eauto.x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
x0: string
v0: expr
t: ty
Henv: value_ok v0 t
v: expr
Hv: value_ok v t1
n: x <> x0
H: env x0 = Some v0value_ok v0 ?tsimpfun.x: string
e: expr
t1, t2: ty
Gamma: ctx
Htyped: typed (insert x t1 Gamma) e t2
IHHtyped: forall env : lec12_termination.env, env_ok env (insert x t1 Gamma) -> expr_ok (subst_map env e) t2
env: lec12_termination.env
Henv: env_ok env Gamma
v: expr
Hv: value_ok v t1delete x env x = Nonee1, e2: expr
t1, t2: ty
Gamma: ctx
Htyped1: typed Gamma e1 (Fun t1 t2)
Htyped2: typed Gamma e2 t1
IHHtyped1: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e1) (Fun t1 t2)
IHHtyped2: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e2) t1
env: lec12_termination.env
Henv: env_ok env Gammaexpr_ok (subst_map env (App e1 e2)) t2e1, e2: expr
t1, t2: ty
Gamma: ctx
Htyped1: typed Gamma e1 (Fun t1 t2)
Htyped2: typed Gamma e2 t1
IHHtyped1: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e1) (Fun t1 t2)
IHHtyped2: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e2) t1
env: lec12_termination.env
Henv: env_ok env Gammaexpr_ok (App (subst_map env e1) (subst_map env e2)) t2e1, e2: expr
t1, t2: ty
Gamma: ctx
Htyped1: typed Gamma e1 (Fun t1 t2)
Htyped2: typed Gamma e2 t1
IHHtyped1: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e1) (Fun t1 t2)
IHHtyped2: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e2) t1
env: lec12_termination.env
Henv: env_ok env Gamma
v1: expr
Hstep1: rtc step (subst_map env e1) v1
Hval1: value_ok v1 (Fun t1 t2)expr_ok (App (subst_map env e1) (subst_map env e2)) t2e1, e2: expr
t1, t2: ty
Gamma: ctx
Htyped1: typed Gamma e1 (Fun t1 t2)
Htyped2: typed Gamma e2 t1
IHHtyped1: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e1) (Fun t1 t2)
IHHtyped2: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e2) t1
env: lec12_termination.env
Henv: env_ok env Gamma
v1: expr
Hstep1: rtc step (subst_map env e1) v1
Hval1: value_ok v1 (Fun t1 t2)
v2: expr
Hstep2: rtc step (subst_map env e2) v2
Hval2: value_ok v2 t1expr_ok (App (subst_map env e1) (subst_map env e2)) t2eapply value_ok_App; eauto.e1, e2: expr
t1, t2: ty
Gamma: ctx
Htyped1: typed Gamma e1 (Fun t1 t2)
Htyped2: typed Gamma e2 t1
IHHtyped1: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e1) (Fun t1 t2)
IHHtyped2: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e2) t1
env: lec12_termination.env
Henv: env_ok env Gamma
v1: expr
Hstep1: rtc step (subst_map env e1) v1
Hval1: value_ok v1 (Fun t1 t2)
v2: expr
Hstep2: rtc step (subst_map env e2) v2
Hval2: value_ok v2 t1expr_ok (App v1 v2) t2Gamma: ctx
env: lec12_termination.env
Henv: env_ok env Gammaexpr_ok (subst_map env Zero) NatGamma: ctx
env: lec12_termination.env
Henv: env_ok env Gammaexpr_ok Zero NatGamma: ctx
env: lec12_termination.env
Henv: env_ok env Gammartc step Zero ?e' /\ value_ok ?e' NatGamma: ctx
env: lec12_termination.env
Henv: env_ok env Gammartc step Zero ?e'Gamma: ctx
env: lec12_termination.env
Henv: env_ok env Gammavalue_ok ?e' Natapply rtc_refl.Gamma: ctx
env: lec12_termination.env
Henv: env_ok env Gammartc step Zero ?e'Gamma: ctx
env: lec12_termination.env
Henv: env_ok env Gammavalue_ok Zero NatGamma: ctx
env: lec12_termination.env
Henv: env_ok env Gammaexists n : nat, Zero = nat_to_expr nauto.Gamma: ctx
env: lec12_termination.env
Henv: env_ok env GammaZero = nat_to_expr 0e: expr
Gamma: ctx
Htyped: typed Gamma e Nat
IHHtyped: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e) Nat
env: lec12_termination.env
Henv: env_ok env Gammaexpr_ok (subst_map env (Succ e)) Nate: expr
Gamma: ctx
Htyped: typed Gamma e Nat
IHHtyped: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e) Nat
env: lec12_termination.env
Henv: env_ok env Gammaexpr_ok (Succ (subst_map env e)) Nate: expr
Gamma: ctx
Htyped: typed Gamma e Nat
IHHtyped: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e) Nat
env: lec12_termination.env
Henv: expr_ok (subst_map env e) Natexpr_ok (Succ (subst_map env e)) Nate: expr
Gamma: ctx
Htyped: typed Gamma e Nat
IHHtyped: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e) Nat
env: lec12_termination.env
e': expr
Hstep: rtc step (subst_map env e) e'
Hval: value_ok e' Natexpr_ok (Succ (subst_map env e)) Nate: expr
Gamma: ctx
Htyped: typed Gamma e Nat
IHHtyped: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e) Nat
env: lec12_termination.env
e': expr
Hstep: rtc step (subst_map env e) e'
Hval: value_ok e' Natrtc step (Succ (subst_map env e)) (Succ e') /\ value_ok (Succ e') Nate: expr
Gamma: ctx
Htyped: typed Gamma e Nat
IHHtyped: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e) Nat
env: lec12_termination.env
e': expr
Hstep: rtc step (subst_map env e) e'
Hval: value_ok e' Natrtc step (Succ (subst_map env e)) (Succ e')e: expr
Gamma: ctx
Htyped: typed Gamma e Nat
IHHtyped: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e) Nat
env: lec12_termination.env
e': expr
Hstep: rtc step (subst_map env e) e'
Hval: value_ok e' Natvalue_ok (Succ e') Nateauto using rtc_step_Succ.e: expr
Gamma: ctx
Htyped: typed Gamma e Nat
IHHtyped: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e) Nat
env: lec12_termination.env
e': expr
Hstep: rtc step (subst_map env e) e'
Hval: value_ok e' Natrtc step (Succ (subst_map env e)) (Succ e')e: expr
Gamma: ctx
Htyped: typed Gamma e Nat
IHHtyped: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e) Nat
env: lec12_termination.env
e': expr
Hstep: rtc step (subst_map env e) e'
Hval: value_ok e' Natvalue_ok (Succ e') Nate: expr
Gamma: ctx
Htyped: typed Gamma e Nat
IHHtyped: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e) Nat
env: lec12_termination.env
e': expr
Hstep: rtc step (subst_map env e) e'
Hval: exists n : nat, e' = nat_to_expr nvalue_ok (Succ e') Nate: expr
Gamma: ctx
Htyped: typed Gamma e Nat
IHHtyped: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e) Nat
env: lec12_termination.env
n: nat
Hstep: rtc step (subst_map env e) (nat_to_expr n)value_ok (Succ (nat_to_expr n)) Nate: expr
Gamma: ctx
Htyped: typed Gamma e Nat
IHHtyped: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e) Nat
env: lec12_termination.env
n: nat
Hstep: rtc step (subst_map env e) (nat_to_expr n)exists n0 : nat, Succ (nat_to_expr n) = nat_to_expr n0auto.e: expr
Gamma: ctx
Htyped: typed Gamma e Nat
IHHtyped: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e) Nat
env: lec12_termination.env
n: nat
Hstep: rtc step (subst_map env e) (nat_to_expr n)Succ (nat_to_expr n) = nat_to_expr (S n)e1, e2, e3: expr
Gamma: ctx
t: ty
Htyped1: typed Gamma e1 Nat
Htyped2: typed Gamma e2 t
Htyped3: typed Gamma e3 (Fun t t)
IHHtyped1: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e1) Nat
IHHtyped2: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e2) t
IHHtyped3: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e3) (Fun t t)
env: lec12_termination.env
Henv: env_ok env Gammaexpr_ok (subst_map env (Rec e1 e2 e3)) te1, e2, e3: expr
Gamma: ctx
t: ty
Htyped1: typed Gamma e1 Nat
Htyped2: typed Gamma e2 t
Htyped3: typed Gamma e3 (Fun t t)
IHHtyped1: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e1) Nat
IHHtyped2: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e2) t
IHHtyped3: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e3) (Fun t t)
env: lec12_termination.env
Henv: env_ok env Gamma
v1: expr
Hstep1: rtc step (subst_map env e1) v1
Hval1: value_ok v1 Natexpr_ok (subst_map env (Rec e1 e2 e3)) te1, e2, e3: expr
Gamma: ctx
t: ty
Htyped1: typed Gamma e1 Nat
Htyped2: typed Gamma e2 t
Htyped3: typed Gamma e3 (Fun t t)
IHHtyped1: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e1) Nat
IHHtyped2: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e2) t
IHHtyped3: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e3) (Fun t t)
env: lec12_termination.env
Henv: env_ok env Gamma
v1: expr
Hstep1: rtc step (subst_map env e1) v1
Hval1: value_ok v1 Nat
v2: expr
Hstep2: rtc step (subst_map env e2) v2
Hval2: value_ok v2 texpr_ok (subst_map env (Rec e1 e2 e3)) te1, e2, e3: expr
Gamma: ctx
t: ty
Htyped1: typed Gamma e1 Nat
Htyped2: typed Gamma e2 t
Htyped3: typed Gamma e3 (Fun t t)
IHHtyped1: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e1) Nat
IHHtyped2: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e2) t
IHHtyped3: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e3) (Fun t t)
env: lec12_termination.env
Henv: env_ok env Gamma
v1: expr
Hstep1: rtc step (subst_map env e1) v1
Hval1: value_ok v1 Nat
v2: expr
Hstep2: rtc step (subst_map env e2) v2
Hval2: value_ok v2 t
v3: expr
Hstep3: rtc step (subst_map env e3) v3
Hval3: value_ok v3 (Fun t t)expr_ok (subst_map env (Rec e1 e2 e3)) te1, e2, e3: expr
Gamma: ctx
t: ty
Htyped1: typed Gamma e1 Nat
Htyped2: typed Gamma e2 t
Htyped3: typed Gamma e3 (Fun t t)
IHHtyped1: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e1) Nat
IHHtyped2: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e2) t
IHHtyped3: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e3) (Fun t t)
env: lec12_termination.env
Henv: env_ok env Gamma
v1: expr
Hstep1: rtc step (subst_map env e1) v1
Hval1: value_ok v1 Nat
v2: expr
Hstep2: rtc step (subst_map env e2) v2
Hval2: value_ok v2 t
v3: expr
Hstep3: rtc step (subst_map env e3) v3
Hval3: value_ok v3 (Fun t t)expr_ok (Rec v1 v2 v3) te1, e2, e3: expr
Gamma: ctx
t: ty
Htyped1: typed Gamma e1 Nat
Htyped2: typed Gamma e2 t
Htyped3: typed Gamma e3 (Fun t t)
IHHtyped1: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e1) Nat
IHHtyped2: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e2) t
IHHtyped3: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e3) (Fun t t)
env: lec12_termination.env
Henv: env_ok env Gamma
v1: expr
Hstep1: rtc step (subst_map env e1) v1
Hval1: exists n : nat, v1 = nat_to_expr n
v2: expr
Hstep2: rtc step (subst_map env e2) v2
Hval2: value_ok v2 t
v3: expr
Hstep3: rtc step (subst_map env e3) v3
Hval3: value_ok v3 (Fun t t)expr_ok (Rec v1 v2 v3) teapply expr_ok_rec; eauto. Defined. (* Final theorem *)e1, e2, e3: expr
Gamma: ctx
t: ty
Htyped1: typed Gamma e1 Nat
Htyped2: typed Gamma e2 t
Htyped3: typed Gamma e3 (Fun t t)
IHHtyped1: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e1) Nat
IHHtyped2: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e2) t
IHHtyped3: forall env : lec12_termination.env, env_ok env Gamma -> expr_ok (subst_map env e3) (Fun t t)
env: lec12_termination.env
Henv: env_ok env Gamma
n1: nat
Hstep1: rtc step (subst_map env e1) (nat_to_expr n1)
v2: expr
Hstep2: rtc step (subst_map env e2) v2
Hval2: value_ok v2 t
v3: expr
Hstep3: rtc step (subst_map env e3) v3
Hval3: value_ok v3 (Fun t t)expr_ok (Rec (nat_to_expr n1) v2 v3) te: expr
t: tytyped empty e t -> terminates ee: expr
t: tytyped empty e t -> terminates ee: expr
t: ty
Htyped: typed empty e tterminates ee: expr
t: ty
Htyped: expr_ok (subst_map empty e) tterminates ee: expr
t: ty
Htyped: typed empty e tenv_ok empty emptye: expr
t: ty
Htyped: expr_ok (subst_map empty e) tterminates ee: expr
t: ty
Htyped: expr_ok e tterminates ee: expr
t: ty
e': expr
Hstep: rtc step e e'
Hval: value_ok e' tterminates ee: expr
t: ty
e': expr
Hstep: rtc step e e'
Hval: value_ok e' trtc step e e' /\ value e'e: expr
t: ty
e': expr
Hstep: rtc step e e'
Hval: value_ok e' tvalue e'eauto.e: expr
t: ty
e': expr
Hstep: rtc step e e'
Hval: value_ok e' tvalue_ok e' ?tconstructor. Defined. (* Definition ack m := rec m S (fun f => fun n => rec (S n) 1 f). *) Definition Ack := Lam "m" (Rec (Var "m") (Lam "x" (Succ (Var "x"))) (Lam "f" (Lam "n" (Rec (Succ (Var "n")) (Succ Zero) (Var "f"))))).e: expr
t: ty
Htyped: typed empty e tenv_ok empty emptytyped empty Ack (Fun Nat (Fun Nat Nat))eauto 20 using typed. Defined. Definition ACK n m := App (App Ack (nat_to_expr n)) (nat_to_expr m).typed empty Ack (Fun Nat (Fun Nat Nat))n: nattyped empty (nat_to_expr n) Natinduction n; simpl; eauto using typed. Defined.n: nattyped empty (nat_to_expr n) Natn, m: nattyped empty (ACK n m) Natn, m: nattyped empty (ACK n m) Nateauto 20 using typed, Ack_typed, nat_to_expr_typed. Defined.n, m: nattyped empty (App (App Ack (nat_to_expr n)) (nat_to_expr m)) Nat