In this lecture, we will define the syntax and semantics of the simply typed lambda calculus. We will then define the typing rules and show that well-typed programs do not get stuck.
(* 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.
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. Definition empty : ctx := fun _ => None. Definition insert (x : string) (t : ty) (Gamma : ctx) : ctx := fun x' => if string_dec x x' then Some t else Gamma x'. 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).
e: expr
t: tytyped empty e t -> value e \/ (exists e' : expr, step e e')e: expr
t: tytyped empty e t -> value e \/ (exists e' : expr, step e e')e: expr
t: ty
Htyped: typed empty e tvalue e \/ (exists e' : expr, step e e')e: expr
t: ty
Gamma: ctx
HeqGamma: Gamma = empty
Htyped: typed Gamma e tvalue e \/ (exists e' : expr, step e e')x: string
t: ty
H: empty x = Some tvalue (Var x) \/ (exists e' : expr, step (Var x) e')x: string
e: expr
t1, t2: ty
IHHtyped: insert x t1 empty = empty -> value e \/ (exists e' : expr, step e e')
Htyped: typed (insert x t1 empty) e t2value (Lam x e) \/ (exists e' : expr, step (Lam x e) e')e1, e2: expr
t1, t2: ty
IHHtyped2: empty = empty -> value e2 \/ (exists e' : expr, step e2 e')
IHHtyped1: empty = empty -> value e1 \/ (exists e' : expr, step e1 e')
Htyped2: typed empty e2 t1
Htyped1: typed empty e1 (Fun t1 t2)value (App e1 e2) \/ (exists e' : expr, step (App e1 e2) e')value Zero \/ (exists e' : expr, step Zero e')e: expr
IHHtyped: empty = empty -> value e \/ (exists e' : expr, step e e')
Htyped: typed empty e Natvalue (Succ e) \/ (exists e' : expr, step (Succ e) e')e1, e2, e3: expr
t: ty
IHHtyped3: empty = empty -> value e3 \/ (exists e' : expr, step e3 e')
IHHtyped2: empty = empty -> value e2 \/ (exists e' : expr, step e2 e')
IHHtyped1: empty = empty -> value e1 \/ (exists e' : expr, step e1 e')
Htyped3: typed empty e3 (Fun t t)
Htyped2: typed empty e2 t
Htyped1: typed empty e1 Natvalue (Rec e1 e2 e3) \/ (exists e' : expr, step (Rec e1 e2 e3) e')x: string
t: ty
H: empty x = Some tvalue (Var x) \/ (exists e' : expr, step (Var x) e')simpeq.x: string
t: ty
H: None = Some tvalue (Var x) \/ (exists e' : expr, step (Var x) e')x: string
e: expr
t1, t2: ty
IHHtyped: insert x t1 empty = empty -> value e \/ (exists e' : expr, step e e')
Htyped: typed (insert x t1 empty) e t2value (Lam x e) \/ (exists e' : expr, step (Lam x e) e')constructor.x: string
e: expr
t1, t2: ty
IHHtyped: insert x t1 empty = empty -> value e \/ (exists e' : expr, step e e')
Htyped: typed (insert x t1 empty) e t2value (Lam x e)e1, e2: expr
t1, t2: ty
IHHtyped2: empty = empty -> value e2 \/ (exists e' : expr, step e2 e')
IHHtyped1: empty = empty -> value e1 \/ (exists e' : expr, step e1 e')
Htyped2: typed empty e2 t1
Htyped1: typed empty e1 (Fun t1 t2)value (App e1 e2) \/ (exists e' : expr, step (App e1 e2) e')e1, e2: expr
t1, t2: ty
IHHtyped2: empty = empty -> value e2 \/ (exists e' : expr, step e2 e')
IHHtyped1: empty = empty -> value e1 \/ (exists e' : expr, step e1 e')
Htyped2: typed empty e2 t1
Htyped1: typed empty e1 (Fun t1 t2)exists e' : expr, step (App e1 e2) e'e1, e2: expr
t1, t2: ty
IHHtyped2: empty = empty -> value e2 \/ (exists e' : expr, step e2 e')
Htyped2: typed empty e2 t1
Htyped1: typed empty e1 (Fun t1 t2)
Hval1: value e1exists e' : expr, step (App e1 e2) e'e1, e2: expr
t1, t2: ty
IHHtyped2: empty = empty -> value e2 \/ (exists e' : expr, step e2 e')
Htyped2: typed empty e2 t1
Htyped1: typed empty e1 (Fun t1 t2)
e1': expr
Hstep1: step e1 e1'exists e' : expr, step (App e1 e2) e'e1, e2: expr
t1, t2: ty
IHHtyped2: empty = empty -> value e2 \/ (exists e' : expr, step e2 e')
Htyped2: typed empty e2 t1
Htyped1: typed empty e1 (Fun t1 t2)
Hval1: value e1exists e' : expr, step (App e1 e2) e'destruct IHHtyped2 as [Hval2 | [e2' Hstep2]]; eauto using step.e2: expr
t1, t2: ty
IHHtyped2: empty = empty -> value e2 \/ (exists e' : expr, step e2 e')
Htyped2: typed empty e2 t1
x: string
e: expr
H1: typed (insert x t1 empty) e t2exists e' : expr, step (App (Lam x e) e2) e'eauto using step.e1, e2: expr
t1, t2: ty
IHHtyped2: empty = empty -> value e2 \/ (exists e' : expr, step e2 e')
Htyped2: typed empty e2 t1
Htyped1: typed empty e1 (Fun t1 t2)
e1': expr
Hstep1: step e1 e1'exists e' : expr, step (App e1 e2) e'value Zero \/ (exists e' : expr, step Zero e')constructor.value Zeroe: expr
IHHtyped: empty = empty -> value e \/ (exists e' : expr, step e e')
Htyped: typed empty e Natvalue (Succ e) \/ (exists e' : expr, step (Succ e) e')e: expr
Htyped: typed empty e Nat
Hval: value evalue (Succ e) \/ (exists e' : expr, step (Succ e) e')e: expr
Htyped: typed empty e Nat
Hval: value evalue (Succ e)eauto.e: expr
Htyped: typed empty e Nat
Hval: value evalue ee1, e2, e3: expr
t: ty
IHHtyped3: empty = empty -> value e3 \/ (exists e' : expr, step e3 e')
IHHtyped2: empty = empty -> value e2 \/ (exists e' : expr, step e2 e')
IHHtyped1: empty = empty -> value e1 \/ (exists e' : expr, step e1 e')
Htyped3: typed empty e3 (Fun t t)
Htyped2: typed empty e2 t
Htyped1: typed empty e1 Natvalue (Rec e1 e2 e3) \/ (exists e' : expr, step (Rec e1 e2 e3) e')e1, e2, e3: expr
t: ty
IHHtyped3: empty = empty -> value e3 \/ (exists e' : expr, step e3 e')
IHHtyped2: empty = empty -> value e2 \/ (exists e' : expr, step e2 e')
Htyped3: typed empty e3 (Fun t t)
Htyped2: typed empty e2 t
Htyped1: typed empty e1 Nat
Hval1: value e1value (Rec e1 e2 e3) \/ (exists e' : expr, step (Rec e1 e2 e3) e')e1, e2, e3: expr
t: ty
IHHtyped3: empty = empty -> value e3 \/ (exists e' : expr, step e3 e')
Htyped3: typed empty e3 (Fun t t)
Htyped2: typed empty e2 t
Htyped1: typed empty e1 Nat
Hval1: value e1
Hval2: value e2value (Rec e1 e2 e3) \/ (exists e' : expr, step (Rec e1 e2 e3) e')e1, e2, e3: expr
t: ty
Htyped3: typed empty e3 (Fun t t)
Htyped2: typed empty e2 t
Htyped1: typed empty e1 Nat
Hval1: value e1
Hval2: value e2
Hval3: value e3value (Rec e1 e2 e3) \/ (exists e' : expr, step (Rec e1 e2 e3) e')e2, e3: expr
t: ty
Htyped3: typed empty e3 (Fun t t)
Htyped2: typed empty e2 t
Hval2: value e2
Hval3: value e3value (Rec Zero e2 e3) \/ (exists e' : expr, step (Rec Zero e2 e3) e')e2, e3: expr
t: ty
Htyped3: typed empty e3 (Fun t t)
Htyped2: typed empty e2 t
e: expr
Hval2: value e2
Hval3: value e3
H: value e
H2: typed empty e Natvalue (Rec (Succ e) e2 e3) \/ (exists e' : expr, step (Rec (Succ e) e2 e3) e')eauto using step.e2, e3: expr
t: ty
Htyped3: typed empty e3 (Fun t t)
Htyped2: typed empty e2 t
Hval2: value e2
Hval3: value e3value (Rec Zero e2 e3) \/ (exists e' : expr, step (Rec Zero e2 e3) e')eauto using step. Qed.e2, e3: expr
t: ty
Htyped3: typed empty e3 (Fun t t)
Htyped2: typed empty e2 t
e: expr
Hval2: value e2
Hval3: value e3
H: value e
H2: typed empty e Natvalue (Rec (Succ e) e2 e3) \/ (exists e' : expr, step (Rec (Succ e) e2 e3) e')
Require Import FunctionalExtensionality.Gamma, Gamma': ctx
e: expr
t: ty(forall (x : string) (t : ty), Gamma x = Some t -> Gamma' x = Some t) -> typed Gamma e t -> typed Gamma' e tGamma, Gamma': ctx
e: expr
t: ty(forall (x : string) (t : ty), Gamma x = Some t -> Gamma' x = Some t) -> typed Gamma e t -> typed Gamma' e tGamma, Gamma': ctx
e: expr
t: ty
Hw: forall (x : string) (t : ty), Gamma x = Some t -> Gamma' x = Some t
H: typed Gamma e ttyped Gamma' e tGamma: ctx
e: expr
t: ty
H: typed Gamma e tforall Gamma' : ctx, (forall (x : string) (t : ty), Gamma x = Some t -> Gamma' x = Some t) -> typed Gamma' e tx: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (insert x t1 Gamma) e t2
IHtyped: forall Gamma' : ctx, (forall (x0 : string) (t : ty), insert x t1 Gamma x0 = Some t -> Gamma' x0 = Some t) -> typed Gamma' e t2
Gamma': ctx
Hw: forall (x : string) (t : ty), Gamma x = Some t -> Gamma' x = Some ttyped Gamma' (Lam x e) (Fun t1 t2)x: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (insert x t1 Gamma) e t2
IHtyped: forall Gamma' : ctx, (forall (x0 : string) (t : ty), insert x t1 Gamma x0 = Some t -> Gamma' x0 = Some t) -> typed Gamma' e t2
Gamma': ctx
Hw: forall (x : string) (t : ty), Gamma x = Some t -> Gamma' x = Some ttyped (insert x t1 Gamma') e t2x: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (insert x t1 Gamma) e t2
IHtyped: forall Gamma' : ctx, (forall (x0 : string) (t : ty), insert x t1 Gamma x0 = Some t -> Gamma' x0 = Some t) -> typed Gamma' e t2
Gamma': ctx
Hw: forall (x : string) (t : ty), Gamma x = Some t -> Gamma' x = Some tforall (x0 : string) (t : ty), insert x t1 Gamma x0 = Some t -> insert x t1 Gamma' x0 = Some tx: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (insert x t1 Gamma) e t2
IHtyped: forall Gamma' : ctx, (forall (x0 : string) (t : ty), insert x t1 Gamma x0 = Some t -> Gamma' x0 = Some t) -> typed Gamma' e t2
Gamma': ctx
Hw: forall (x : string) (t : ty), Gamma x = Some t -> Gamma' x = Some tforall (x0 : string) (t : ty), (if string_dec x x0 then Some t1 else Gamma x0) = Some t -> (if string_dec x x0 then Some t1 else Gamma' x0) = Some tx: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (insert x t1 Gamma) e t2
IHtyped: forall Gamma' : ctx, (forall (x0 : string) (t : ty), insert x t1 Gamma x0 = Some t -> Gamma' x0 = Some t) -> typed Gamma' e t2
Gamma': ctx
Hw: forall (x : string) (t : ty), Gamma x = Some t -> Gamma' x = Some t
x0: string
t: ty
H0: (if string_dec x x0 then Some t1 else Gamma x0) = Some t(if string_dec x x0 then Some t1 else Gamma' x0) = Some teauto. Qed.x: string
e: expr
t1, t2: ty
Gamma: ctx
H: typed (insert x t1 Gamma) e t2
IHtyped: forall Gamma' : ctx, (forall (x0 : string) (t : ty), insert x t1 Gamma x0 = Some t -> Gamma' x0 = Some t) -> typed Gamma' e t2
Gamma': ctx
Hw: forall (x : string) (t : ty), Gamma x = Some t -> Gamma' x = Some t
x0: string
t: ty
n: x <> x0
H0: Gamma x0 = Some tGamma' x0 = Some tGamma: ctx
x: string
v, e: expr
t, tv: tytyped empty v tv -> typed (insert x tv Gamma) e t -> typed Gamma (subst x v e) tGamma: ctx
x: string
v, e: expr
t, tv: tytyped empty v tv -> typed (insert x tv Gamma) e t -> typed Gamma (subst x v e) tGamma: ctx
x: string
v, e: expr
t, tv: ty
Hv: typed empty v tv
H: typed (insert x tv Gamma) e ttyped Gamma (subst x v e) tGamma: ctx
x: string
v, e: expr
t, tv: ty
Hv: typed empty v tv
Gamma': ctx
HeqGamma': Gamma' = insert x tv Gamma
H: typed Gamma' e ttyped Gamma (subst x v e) tx: string
v, e: expr
t, tv: ty
Hv: typed empty v tv
Gamma': ctx
H: typed Gamma' e tforall Gamma : ctx, Gamma' = insert x tv Gamma -> typed Gamma (subst x v e) tx: string
v: expr
tv: ty
Hv: typed empty v tv
x0: string
t: ty
Gamma0: ctx
H: insert x tv Gamma0 x0 = Some ttyped Gamma0 (if string_dec x x0 then v else Var x0) tx: string
v: expr
tv: ty
Hv: typed empty v tv
x0: string
e: expr
t1, t2: ty
Gamma0: ctx
IHtyped: forall Gamma : ctx, insert x0 t1 (insert x tv Gamma0) = insert x tv Gamma -> typed Gamma (subst x v e) t2
H: typed (insert x0 t1 (insert x tv Gamma0)) e t2typed Gamma0 (Lam x0 (if string_dec x x0 then e else subst x v e)) (Fun t1 t2)x: string
v: expr
tv: ty
Hv: typed empty v tv
x0: string
t: ty
Gamma0: ctx
H: insert x tv Gamma0 x0 = Some ttyped Gamma0 (if string_dec x x0 then v else Var x0) tx: string
v: expr
tv: ty
Hv: typed empty v tv
x0: string
t: ty
Gamma0: ctx
H: (if string_dec x x0 then Some tv else Gamma0 x0) = Some ttyped Gamma0 (if string_dec x x0 then v else Var x0) tv: expr
t: ty
Hv: typed empty v t
x0: string
Gamma0: ctxtyped Gamma0 v tv: expr
t: ty
Hv: typed empty v t
x0: string
Gamma0: ctxforall (x : string) (t : ty), empty x = Some t -> Gamma0 x = Some tv: expr
t: ty
Hv: typed empty v t
x0: string
Gamma0: ctx
x: string
t0: ty
H: empty x = Some t0Gamma0 x = Some t0simpeq.v: expr
t: ty
Hv: typed empty v t
x0: string
Gamma0: ctx
x: string
t0: ty
H: None = Some t0Gamma0 x = Some t0x: string
v: expr
tv: ty
Hv: typed empty v tv
x0: string
e: expr
t1, t2: ty
Gamma0: ctx
IHtyped: forall Gamma : ctx, insert x0 t1 (insert x tv Gamma0) = insert x tv Gamma -> typed Gamma (subst x v e) t2
H: typed (insert x0 t1 (insert x tv Gamma0)) e t2typed Gamma0 (Lam x0 (if string_dec x x0 then e else subst x v e)) (Fun t1 t2)x: string
v: expr
tv: ty
Hv: typed empty v tv
x0: string
e: expr
t1, t2: ty
Gamma0: ctx
IHtyped: forall Gamma : ctx, insert x0 t1 (insert x tv Gamma0) = insert x tv Gamma -> typed Gamma (subst x v e) t2
H: typed (insert x0 t1 (insert x tv Gamma0)) e t2typed (insert x0 t1 Gamma0) (if string_dec x x0 then e else subst x v e) t2v: expr
tv: ty
Hv: typed empty v tv
x0: string
e: expr
t1, t2: ty
Gamma0: ctx
H: typed (insert x0 t1 (insert x0 tv Gamma0)) e t2
IHtyped: forall Gamma : ctx, insert x0 t1 (insert x0 tv Gamma0) = insert x0 tv Gamma -> typed Gamma (subst x0 v e) t2typed (insert x0 t1 Gamma0) e t2x: string
v: expr
tv: ty
Hv: typed empty v tv
x0: string
e: expr
t1, t2: ty
Gamma0: ctx
IHtyped: forall Gamma : ctx, insert x0 t1 (insert x tv Gamma0) = insert x tv Gamma -> typed Gamma (subst x v e) t2
H: typed (insert x0 t1 (insert x tv Gamma0)) e t2
n: x <> x0typed (insert x0 t1 Gamma0) (subst x v e) t2v: expr
tv: ty
Hv: typed empty v tv
x0: string
e: expr
t1, t2: ty
Gamma0: ctx
H: typed (insert x0 t1 (insert x0 tv Gamma0)) e t2
IHtyped: forall Gamma : ctx, insert x0 t1 (insert x0 tv Gamma0) = insert x0 tv Gamma -> typed Gamma (subst x0 v e) t2typed (insert x0 t1 Gamma0) e t2v: expr
tv: ty
Hv: typed empty v tv
x0: string
e: expr
t1, t2: ty
Gamma0: ctx
H: typed (insert x0 t1 (insert x0 tv Gamma0)) e t2
IHtyped: forall Gamma : ctx, insert x0 t1 (insert x0 tv Gamma0) = insert x0 tv Gamma -> typed Gamma (subst x0 v e) t2forall (x : string) (t : ty), insert x0 t1 (insert x0 tv Gamma0) x = Some t -> insert x0 t1 Gamma0 x = Some tv: expr
tv: ty
Hv: typed empty v tv
x0: string
e: expr
t1, t2: ty
Gamma0: ctx
H: typed (insert x0 t1 (insert x0 tv Gamma0)) e t2
IHtyped: forall Gamma : ctx, insert x0 t1 (insert x0 tv Gamma0) = insert x0 tv Gamma -> typed Gamma (subst x0 v e) t2forall (x : string) (t : ty), (if string_dec x0 x then Some t1 else if string_dec x0 x then Some tv else Gamma0 x) = Some t -> (if string_dec x0 x then Some t1 else Gamma0 x) = Some tdestruct string_dec; simpeq.v: expr
tv: ty
Hv: typed empty v tv
x0: string
e: expr
t1, t2: ty
Gamma0: ctx
H: typed (insert x0 t1 (insert x0 tv Gamma0)) e t2
IHtyped: forall Gamma : ctx, insert x0 t1 (insert x0 tv Gamma0) = insert x0 tv Gamma -> typed Gamma (subst x0 v e) t2
x: string
t: ty
H0: (if string_dec x0 x then Some t1 else if string_dec x0 x then Some tv else Gamma0 x) = Some t(if string_dec x0 x then Some t1 else Gamma0 x) = Some tx: string
v: expr
tv: ty
Hv: typed empty v tv
x0: string
e: expr
t1, t2: ty
Gamma0: ctx
IHtyped: forall Gamma : ctx, insert x0 t1 (insert x tv Gamma0) = insert x tv Gamma -> typed Gamma (subst x v e) t2
H: typed (insert x0 t1 (insert x tv Gamma0)) e t2
n: x <> x0typed (insert x0 t1 Gamma0) (subst x v e) t2x: string
v: expr
tv: ty
Hv: typed empty v tv
x0: string
e: expr
t1, t2: ty
Gamma0: ctx
IHtyped: forall Gamma : ctx, insert x0 t1 (insert x tv Gamma0) = insert x tv Gamma -> typed Gamma (subst x v e) t2
H: typed (insert x0 t1 (insert x tv Gamma0)) e t2
n: x <> x0insert x0 t1 (insert x tv Gamma0) = insert x tv (insert x0 t1 Gamma0)x: string
v: expr
tv: ty
Hv: typed empty v tv
x0: string
e: expr
t1, t2: ty
Gamma0: ctx
IHtyped: forall Gamma : ctx, insert x0 t1 (insert x tv Gamma0) = insert x tv Gamma -> typed Gamma (subst x v e) t2
H: typed (insert x0 t1 (insert x tv Gamma0)) e t2
n: x <> x0forall x1 : string, insert x0 t1 (insert x tv Gamma0) x1 = insert x tv (insert x0 t1 Gamma0) x1x: string
v: expr
tv: ty
Hv: typed empty v tv
x0: string
e: expr
t1, t2: ty
Gamma0: ctx
IHtyped: forall Gamma : ctx, insert x0 t1 (insert x tv Gamma0) = insert x tv Gamma -> typed Gamma (subst x v e) t2
H: typed (insert x0 t1 (insert x tv Gamma0)) e t2
n: x <> x0
x1: stringinsert x0 t1 (insert x tv Gamma0) x1 = insert x tv (insert x0 t1 Gamma0) x1x: string
v: expr
tv: ty
Hv: typed empty v tv
x0: string
e: expr
t1, t2: ty
Gamma0: ctx
IHtyped: forall Gamma : ctx, insert x0 t1 (insert x tv Gamma0) = insert x tv Gamma -> typed Gamma (subst x v e) t2
H: typed (insert x0 t1 (insert x tv Gamma0)) e t2
n: x <> x0
x1: string(if string_dec x0 x1 then Some t1 else if string_dec x x1 then Some tv else Gamma0 x1) = (if string_dec x x1 then Some tv else if string_dec x0 x1 then Some t1 else Gamma0 x1)destruct string_dec; simpeq. Qed.x: string
v: expr
tv: ty
Hv: typed empty v tv
e: expr
t1, t2: ty
Gamma0: ctx
x1: string
n: x <> x1
H: typed (insert x1 t1 (insert x tv Gamma0)) e t2
IHtyped: forall Gamma : ctx, insert x1 t1 (insert x tv Gamma0) = insert x tv Gamma -> typed Gamma (subst x v e) t2Some t1 = (if string_dec x x1 then Some tv else Some t1)e, e': expr
t: tytyped empty e t -> step e e' -> typed empty e' te, e': expr
t: tytyped empty e t -> step e e' -> typed empty e' te, e': expr
t: ty
Htyped: typed empty e t
Hstep: step e e'typed empty e' te, e': expr
Hstep: step e e'forall t : ty, typed empty e t -> typed empty e' tx: string
v, e: expr
H: value v
t, t1: ty
H3: typed empty (Lam x e) (Fun t1 t)
H5: typed empty v t1typed empty (subst x v e) te1, e2, e3: expr
H: value e1
H0: value e2
H1: value e3
t: ty
H6: typed empty (Succ e1) Nat
H8: typed empty e2 t
H9: typed empty e3 (Fun t t)typed empty (Rec e1 (App e3 e2) e3) tx: string
v, e: expr
H: value v
t, t1: ty
H3: typed empty (Lam x e) (Fun t1 t)
H5: typed empty v t1typed empty (subst x v e) tx: string
v, e: expr
H: value v
t, t1: ty
H5: typed empty v t1
H2: typed (insert x t1 empty) e ttyped empty (subst x v e) teapply subst_typed; eauto.x: string
v, e: expr
H: value v
t, t1: ty
H5: typed empty v t1
H2: typed (insert x t1 empty) e ttyped empty (subst x v e) te1, e2, e3: expr
H: value e1
H0: value e2
H1: value e3
t: ty
H6: typed empty (Succ e1) Nat
H8: typed empty e2 t
H9: typed empty e3 (Fun t t)typed empty (Rec e1 (App e3 e2) e3) te1, e2, e3: expr
H: value e1
H0: value e2
H1: value e3
t: ty
H8: typed empty e2 t
H9: typed empty e3 (Fun t t)
H4: typed empty e1 Nattyped empty (Rec e1 (App e3 e2) e3) teconstructor; eauto. Qed.e1, e2, e3: expr
H: value e1
H0: value e2
H1: value e3
t: ty
H8: typed empty e2 t
H9: typed empty e3 (Fun t t)
H4: typed empty e1 Nattyped empty (App e3 e2) t
Inductive rtc {A} (R : A -> A -> Prop) : A -> A -> Prop := | rtc_refl (x : A) : rtc R x x | rtc_trans (x y z : A) : R x y -> rtc R y z -> rtc R x z. Definition safe (e : expr) := forall e', rtc step e e' -> value e' \/ exists e'', step e' e''.e: expr
t: tytyped empty e t -> safe ee: expr
t: tytyped empty e t -> safe ee: expr
t: tytyped empty e t -> forall e' : expr, rtc step e e' -> value e' \/ (exists e'' : expr, step e' e'')e: expr
t: ty
Htyped: typed empty e t
e': expr
Hstep: rtc step e e'value e' \/ (exists e'' : expr, step e' e'')e: expr
t: ty
Htyped: typed empty e t
e': expr
Hstep: rtc step e e'typed empty e' te: expr
t: ty
Htyped: typed empty e t
e': expr
Hstep: rtc step e e'
H: typed empty e' tvalue e' \/ (exists e'' : expr, step e' e'')induction Hstep; eauto using preservation.e: expr
t: ty
Htyped: typed empty e t
e': expr
Hstep: rtc step e e'typed empty e' te: expr
t: ty
Htyped: typed empty e t
e': expr
Hstep: rtc step e e'
H: typed empty e' tvalue e' \/ (exists e'' : expr, step e' e'')eauto. Qed.e: expr
t: ty
Htyped: typed empty e t
e': expr
Hstep: rtc step e e'
H: typed empty e' ttyped empty e' ?t