Type checking for the simply typed lambda calculus
InductiveRaw lambda terms#✓fully proved
Raw terms are extrinsic de Bruijn syntax over a given type of base types: a raw term is either a variable given by a natural-number index \(n\), an application \(f\,a\) of two raw terms \(f\) and \(a\), or a lambda abstraction \(\lambda A.\,t\) consisting of a simple type \(A\) over the base types (the parameter type) and a raw term \(t\) (the body). Variables and applications carry no type information.
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
inductive Ty (Base : Type u) where
| base : Base → Ty Base
| arr : Ty Base → Ty Base → Ty Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:36
Uses 1 · Used by 54
DefinitionSize of a raw term#✓fully proved
Writing \(|t|\) for the size of a raw term \(t\), the size counts the syntax nodes of \(t\): a variable has size \(1\), an application \(f\,a\) has size \(|f| + |a| + 1\), and a lambda abstraction \(\lambda A.\,t\) has size \(|t| + 1\), so the type annotation \(A\) is not counted.
def size : RawTm Base → Nat
| .var _ => 1
| .app f a => f.size + a.size + 1
| .lam _ body => body.size + 1
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
Uses 2 · Used by 2
DefinitionShifting raw terms#✓fully proved
For natural numbers \(k\) (the amount) and \(c\) (the cutoff, \(0\) by default), shifting a raw term by \(k\) at cutoff \(c\) replaces a variable index \(n\) by \(n + k\) if \(c \le n\) and leaves it unchanged otherwise, shifts both sides of an application by \(k\) at cutoff \(c\), and sends \(\lambda A.\,t\) to \(\lambda A.\,t'\), where \(t'\) is \(t\) shifted by \(k\) at cutoff \(c + 1\).
def shift (amount : Nat) (cutoff : Nat := 0) : RawTm Base → RawTm Base
| .var n => .var (if cutoff ≤ n then n + amount else n)
| .app f a => .app (f.shift amount cutoff) (a.shift amount cutoff)
| .lam A body => .lam A (body.shift amount (cutoff + 1))
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
Uses 2 · Used by 1
DefinitionVariable lookup#✓fully proved
Given a context \(\Gamma\), a list of types, and a natural number \(n\), looking up the de Bruijn index \(n\) in \(\Gamma\) either fails or returns a type \(A\) together with an intrinsic variable of type \(A\) in \(\Gamma\). It is defined by recursion: lookup fails in the empty context; index \(0\) in the context \(A :: \Gamma\), obtained by adding \(A\) at the front of \(\Gamma\), returns \(A\) with the zero variable; and index \(n + 1\) in \(B :: \Gamma\) looks up \(n\) in \(\Gamma\), fails if that fails, and otherwise returns the same type with the successor of the variable found.
def lookupVar : (Γ : List (Ty Base)) → Nat →
Option (Sigma fun A => Var Γ A)
| [], _ => none
| A :: _, 0 => some ⟨A, .zero⟩
| _ :: Γ, n + 1 => do
let ⟨A, x⟩ ← lookupVar Γ n
pure ⟨A, .succ x⟩
inductive Ty (Base : Type u) where
| base : Base → Ty Base
| arr : Ty Base → Ty Base → Ty Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:36
inductive Var {Base : Type u} : List (Ty Base) → Ty Base → Type u where
| zero {A : Ty Base} {Γ : List (Ty Base)} : Var (A :: Γ) A
| succ {A B : Ty Base} {Γ : List (Ty Base)} : Var Γ A → Var (B :: Γ) A
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:56
Uses 2 · Used by 11
DefinitionIndex of a typed variable#✓fully proved
For a context \(\Gamma\) and a type \(A\), a well-typed de Bruijn variable of type \(A\) in \(\Gamma\) is sent to its natural-number index, forgetting its type: the variable for the first entry of the context has index \(0\), and the successor of a variable \(x\) has the index of \(x\) plus \(1\).
def Var.toNat {Base : Type u} {Γ : List (Ty Base)} {A : Ty Base} : Var Γ A → Nat
| .zero => 0
| .succ x => x.toNat + 1
inductive Ty (Base : Type u) where
| base : Base → Ty Base
| arr : Ty Base → Ty Base → Ty Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:36
inductive Var {Base : Type u} : List (Ty Base) → Ty Base → Type u where
| zero {A : Ty Base} {Γ : List (Ty Base)} : Var (A :: Γ) A
| succ {A B : Ty Base} {Γ : List (Ty Base)} : Var Γ A → Var (B :: Γ) A
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:56
Uses 2 · Used by 12
TheoremLookup recovers an intrinsic variable from its index#✓fully proved
For every context \(\Gamma\), type \(A\) and intrinsic variable \(x\) of type \(A\) in \(\Gamma\), looking up the de Bruijn index of \(x\) in \(\Gamma\) succeeds and returns the type \(A\) together with \(x\).
@[simp] theorem lookupVar_toNat {Base : Type u} {Γ : List (Ty Base)} {A : Ty Base}
(x : Var Γ A) :
lookupVar Γ x.toNat = some ⟨A, x⟩
inductive Ty (Base : Type u) where
| base : Base → Ty Base
| arr : Ty Base → Ty Base → Ty Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:36
inductive Var {Base : Type u} : List (Ty Base) → Ty Base → Type u where
| zero {A : Ty Base} {Γ : List (Ty Base)} : Var (A :: Γ) A
| succ {A B : Ty Base} {Γ : List (Ty Base)} : Var Γ A → Var (B :: Γ) A
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:56
def lookupVar : (Γ : List (Ty Base)) → Nat →
Option (Sigma fun A => Var Γ A)
| [], _ => none
| A :: _, 0 => some ⟨A, .zero⟩
| _ :: Γ, n + 1 => do
let ⟨A, x⟩ ← lookupVar Γ n
pure ⟨A, .succ x⟩
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:82
Uses 4 · Used by 2
TheoremLookup returns a variable with the queried index#✓fully proved
For every context \(\Gamma\) and natural number \(n\), if looking up the de Bruijn index \(n\) in \(\Gamma\) succeeds with a type \(A\) and an intrinsic variable \(x\) of type \(A\) in \(\Gamma\), then the de Bruijn index of \(x\) is \(n\).
theorem lookupVar_result_toNat {Base : Type u} {Γ : List (Ty Base)}
{n : Nat} {result : Sigma fun A => Var Γ A}
(h : lookupVar Γ n = some result) : result.2.toNat = n
inductive Ty (Base : Type u) where
| base : Base → Ty Base
| arr : Ty Base → Ty Base → Ty Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:36
inductive Var {Base : Type u} : List (Ty Base) → Ty Base → Type u where
| zero {A : Ty Base} {Γ : List (Ty Base)} : Var (A :: Γ) A
| succ {A B : Ty Base} {Γ : List (Ty Base)} : Var Γ A → Var (B :: Γ) A
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:56
def lookupVar : (Γ : List (Ty Base)) → Nat →
Option (Sigma fun A => Var Γ A)
| [], _ => none
| A :: _, 0 => some ⟨A, .zero⟩
| _ :: Γ, n + 1 => do
let ⟨A, x⟩ ← lookupVar Γ n
pure ⟨A, .succ x⟩
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:82
Uses 4 · Used by 2
DefinitionErasure of intrinsically typed terms#✓fully proved
The erasure of an intrinsically typed term in a context \(\Gamma\) is the raw term defined by recursion: a variable becomes the raw variable whose index is its position in \(\Gamma\) (counting from \(0\) at the front); an application of \(f\) to \(a\) becomes the raw application of the erasure of \(f\) to the erasure of \(a\); and a lambda with parameter type \(B\) becomes the raw lambda annotated with \(B\) whose body is the erasure of its body. Erasure thus forgets all typing information except the binder annotations.
def Tm.erase {Base : Type u} {Γ : List (Ty Base)} {A : Ty Base} :
Tm Γ A → RawTm Base
| .var x => .var x.toNat
| .app f a => .app f.erase a.erase
| .lam (A := A) body => .lam A body.erase
inductive Ty (Base : Type u) where
| base : Base → Ty Base
| arr : Ty Base → Ty Base → Ty Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:36
inductive Tm {Base : Type u} : List (Ty Base) → Ty Base → Type u where
| var {A : Ty Base} {Γ : List (Ty Base)} : Var Γ A → Tm Γ A
| app {A B : Ty Base} {Γ : List (Ty Base)} : Tm Γ (A ⇒ B) → Tm Γ A → Tm Γ B
| lam {A B : Ty Base} {Γ : List (Ty Base)} : Tm (A :: Γ) B → Tm Γ (A ⇒ B)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:61
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
Uses 5 · Used by 13
AbbreviationChecked terms#✓fully proved
For a context \(\Gamma\) of simple types, a checked term in \(\Gamma\) is a pair \((A, t)\) of a simple type \(A\) and an intrinsically typed term \(t\) of type \(A\) in \(\Gamma\).
A successful elaboration returns such a pair: the inferred type together with an intrinsic term at that type.
abbrev Checked (Base : Type u) (Γ : List (Ty Base)) :=
Sigma fun A => Tm Γ A
inductive Ty (Base : Type u) where
| base : Base → Ty Base
| arr : Ty Base → Ty Base → Ty Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:36
inductive Tm {Base : Type u} : List (Ty Base) → Ty Base → Type u where
| var {A : Ty Base} {Γ : List (Ty Base)} : Var Γ A → Tm Γ A
| app {A B : Ty Base} {Γ : List (Ty Base)} : Tm Γ (A ⇒ B) → Tm Γ A → Tm Γ B
| lam {A B : Ty Base} {Γ : List (Ty Base)} : Tm (A :: Γ) B → Tm Γ (A ⇒ B)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:61
Uses 2 · Used by 13
DefinitionElaboration of raw STLC terms#✓fully proved
Assume equality of base types is decidable. Elaboration in a context \(\Gamma\) of simple types sends a raw term either to failure or to a checked term in \(\Gamma\) (a simple type together with an intrinsically typed term of that type in \(\Gamma\)), by recursion on the raw term. A variable with de Bruijn index \(n\) elaborates to the variable at position \(n\) of \(\Gamma\) (counting from \(0\) at the front), with the type stored there, and fails if \(\Gamma\) has at most \(n\) entries. A lambda with parameter type \(A\) and body \(b\) elaborates \(b\) in \(\Gamma\) extended by \(A\) at the front; if that gives type \(B\), it returns the lambda at type \(A \to B\), and otherwise it fails. An application of \(f\) to \(a\) elaborates \(f\) and \(a\) in \(\Gamma\), and succeeds, returning the application at type \(B\), exactly when \(f\) gets a function type \(A \to B\) and \(a\) gets type \(A\); otherwise it fails.
Cslib.Languages.LambdaCalculus.Stlc.elaborate · 16 lines
def elaborate [DecidableEq Base] (Γ : List (Ty Base)) :
RawTm Base → Option (Checked Base Γ)
| .var n => lookupVar Γ n
|>.map fun ⟨A, x⟩ => ⟨A, .var x⟩
| .lam A body => do
let ⟨B, body'⟩ ← elaborate (A :: Γ) body
pure ⟨A ⇒ B, .lam body'⟩
| .app f a => do
let ⟨F, f'⟩ ← elaborate Γ f
match F, f' with
| .base _, _ => none
| A ⇒ B, f' =>
let ⟨A', a'⟩ ← elaborate Γ a
if h : A' = A then
pure ⟨B, .app f' (h ▸ a')⟩
else none
inductive Ty (Base : Type u) where
| base : Base → Ty Base
| arr : Ty Base → Ty Base → Ty Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:36
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
abbrev Checked (Base : Type u) (Γ : List (Ty Base)) :=
Sigma fun A => Tm Γ A
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:150
def lookupVar : (Γ : List (Ty Base)) → Nat →
Option (Sigma fun A => Var Γ A)
| [], _ => none
| A :: _, 0 => some ⟨A, .zero⟩
| _ :: Γ, n + 1 => do
let ⟨A, x⟩ ← lookupVar Γ n
pure ⟨A, .succ x⟩
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:82
Uses 6 · Used by 13
TheoremElaboration inverts erasure#✓fully proved
Assume equality of base types is decidable. For every intrinsically typed term \(t\) of type \(A\) in context \(\Gamma\), elaborating the erasure of \(t\) in \(\Gamma\) succeeds and returns exactly the pair \((A, t)\). In other words, erasure is a section of elaboration.
@[simp] theorem elaborate_erase [DecidableEq Base] (t : Tm Γ A) :
elaborate (Base := Base) Γ t.erase = some ⟨A, t⟩
inductive Tm {Base : Type u} : List (Ty Base) → Ty Base → Type u where
| var {A : Ty Base} {Γ : List (Ty Base)} : Var Γ A → Tm Γ A
| app {A B : Ty Base} {Γ : List (Ty Base)} : Tm Γ (A ⇒ B) → Tm Γ A → Tm Γ B
| lam {A B : Ty Base} {Γ : List (Ty Base)} : Tm (A :: Γ) B → Tm Γ (A ⇒ B)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:61
def elaborate [DecidableEq Base] (Γ : List (Ty Base)) :
RawTm Base → Option (Checked Base Γ)
| .var n => lookupVar Γ n
|>.map fun ⟨A, x⟩ => ⟨A, .var x⟩
| .lam A body => do
let ⟨B, body'⟩ ← elaborate (A :: Γ) body
pure ⟨A ⇒ B, .lam body'⟩
| .app f a => do
let ⟨F, f'⟩ ← elaborate Γ f
match F, f' with
| .base _, _ => none
| A ⇒ B, f' =>
⋯
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:154
Uses 10 · Used by 3
TheoremElaboration preserves the input syntax#✓fully proved
Assume equality of base types is decidable. If elaborating a raw term \(r\) in context \(\Gamma\) succeeds with type \(A\) and intrinsically typed term \(t\), then the erasure of \(t\) is exactly \(r\).
theorem elaborate_faithful [DecidableEq Base] {raw : RawTm Base}
{t : Tm Γ A} (h : elaborate Γ raw = some ⟨A, t⟩) :
t.erase = raw
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
inductive Tm {Base : Type u} : List (Ty Base) → Ty Base → Type u where
| var {A : Ty Base} {Γ : List (Ty Base)} : Var Γ A → Tm Γ A
| app {A B : Ty Base} {Γ : List (Ty Base)} : Tm Γ (A ⇒ B) → Tm Γ A → Tm Γ B
| lam {A B : Ty Base} {Γ : List (Ty Base)} : Tm (A :: Γ) B → Tm Γ (A ⇒ B)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:61
def elaborate [DecidableEq Base] (Γ : List (Ty Base)) :
RawTm Base → Option (Checked Base Γ)
| .var n => lookupVar Γ n
|>.map fun ⟨A, x⟩ => ⟨A, .var x⟩
| .lam A body => do
let ⟨B, body'⟩ ← elaborate (A :: Γ) body
pure ⟨A ⇒ B, .lam body'⟩
| .app f a => do
let ⟨F, f'⟩ ← elaborate Γ f
match F, f' with
| .base _, _ => none
| A ⇒ B, f' =>
⋯
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:154
TheoremErasure is injective#✓fully proved
For a fixed context \(\Gamma\) and type \(A\), erasure is injective on intrinsically typed terms of type \(A\) in \(\Gamma\): two such terms with the same erasure are equal.
theorem Tm.erase_injective :
Function.Injective (@Tm.erase Base Γ A)
def Tm.erase {Base : Type u} {Γ : List (Ty Base)} {A : Ty Base} :
Tm Γ A → RawTm Base
| .var x => .var x.toNat
| .app f a => .app f.erase a.erase
| .lam (A := A) body => .lam A body.erase
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:133
InductiveDeclarative typing of raw terms#✓fully proved
For a context \(\Gamma\) (a list of simple types), a raw term \(t\) and a type \(A\), the judgment \(\Gamma \vdash t : A\) is the least relation closed under three rules. A variable with de Bruijn index \(n\) has type \(A\) in \(\Gamma\) whenever looking up \(n\) in \(\Gamma\) succeeds with the type \(A\) and some intrinsic variable of type \(A\). If \(\Gamma \vdash f : A \Rightarrow B\) and \(\Gamma \vdash a : A\), then the application \(f\,a\) has type \(B\) in \(\Gamma\). If \(A :: \Gamma \vdash b : B\), where \(A :: \Gamma\) is \(\Gamma\) with \(A\) added at the front, then the abstraction \(\lambda{:}A.\,b\) with parameter type \(A\) has type \(A \Rightarrow B\) in \(\Gamma\).
inductive HasType : (Γ : List (Ty Base)) → RawTm Base → Ty Base → Prop where
| var {Γ : List (Ty Base)} {A : Ty Base} {n : Nat} {x : Var Γ A}
(h : lookupVar Γ n = some ⟨A, x⟩) : HasType Γ (.var n) A
| app {Γ : List (Ty Base)} {A B : Ty Base} {f a : RawTm Base} :
HasType Γ f (A ⇒ B) → HasType Γ a A → HasType Γ (.app f a) B
| lam {Γ : List (Ty Base)} {A B : Ty Base} {body : RawTm Base} :
HasType (A :: Γ) body B → HasType Γ (.lam A body) (A ⇒ B)
inductive Ty (Base : Type u) where
| base : Base → Ty Base
| arr : Ty Base → Ty Base → Ty Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:36
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
inductive Var {Base : Type u} : List (Ty Base) → Ty Base → Type u where
| zero {A : Ty Base} {Γ : List (Ty Base)} : Var (A :: Γ) A
| succ {A B : Ty Base} {Γ : List (Ty Base)} : Var Γ A → Var (B :: Γ) A
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:56
def lookupVar : (Γ : List (Ty Base)) → Nat →
Option (Sigma fun A => Var Γ A)
| [], _ => none
| A :: _, 0 => some ⟨A, .zero⟩
| _ :: Γ, n + 1 => do
let ⟨A, x⟩ ← lookupVar Γ n
pure ⟨A, .succ x⟩
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:82
Uses 4 · Used by 8
TheoremErasure preserves typing#✓fully proved
For every intrinsically typed term \(t\) of type \(A\) in context \(\Gamma\), the erasure of \(t\) has type \(A\) in \(\Gamma\) under the declarative typing judgment for raw terms.
theorem erase (t : Tm Γ A) : HasType Γ t.erase A
inductive Tm {Base : Type u} : List (Ty Base) → Ty Base → Type u where
| var {A : Ty Base} {Γ : List (Ty Base)} : Var Γ A → Tm Γ A
| app {A B : Ty Base} {Γ : List (Ty Base)} : Tm Γ (A ⇒ B) → Tm Γ A → Tm Γ B
| lam {A B : Ty Base} {Γ : List (Ty Base)} : Tm (A :: Γ) B → Tm Γ (A ⇒ B)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:61
inductive HasType : (Γ : List (Ty Base)) → RawTm Base → Ty Base → Prop where
| var {Γ : List (Ty Base)} {A : Ty Base} {n : Nat} {x : Var Γ A}
(h : lookupVar Γ n = some ⟨A, x⟩) : HasType Γ (.var n) A
| app {Γ : List (Ty Base)} {A B : Ty Base} {f a : RawTm Base} :
HasType Γ f (A ⇒ B) → HasType Γ a A → HasType Γ (.app f a) B
| lam {Γ : List (Ty Base)} {A B : Ty Base} {body : RawTm Base} :
HasType (A :: Γ) body B → HasType Γ (.lam A body) (A ⇒ B)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:239
Uses 9 · Used by 2
TheoremUniqueness of types for raw terms#✓fully proved
Let \(\Gamma\) be a context of simple types and \(r\) a raw term. If \(r\) has type \(A\) in \(\Gamma\) and \(r\) has type \(B\) in \(\Gamma\) under the declarative typing judgment for raw terms, then \(A = B\).
theorem unique {raw : RawTm Base} (hA : HasType Γ raw A)
(hB : HasType Γ raw B) : A = B
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
inductive HasType : (Γ : List (Ty Base)) → RawTm Base → Ty Base → Prop where
| var {Γ : List (Ty Base)} {A : Ty Base} {n : Nat} {x : Var Γ A}
(h : lookupVar Γ n = some ⟨A, x⟩) : HasType Γ (.var n) A
| app {Γ : List (Ty Base)} {A B : Ty Base} {f a : RawTm Base} :
HasType Γ f (A ⇒ B) → HasType Γ a A → HasType Γ (.app f a) B
| lam {Γ : List (Ty Base)} {A B : Ty Base} {body : RawTm Base} :
HasType (A :: Γ) body B → HasType Γ (.lam A body) (A ⇒ B)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:239
Uses 5
TheoremCompleteness of elaboration#✓fully proved
Assume equality of base types is decidable. If a raw term \(r\) has type \(A\) in context \(\Gamma\) under the declarative typing judgment, then elaborating \(r\) in \(\Gamma\) succeeds and returns the type \(A\) together with some intrinsically typed term of type \(A\) in \(\Gamma\).
theorem elaborate_complete [DecidableEq Base] {raw : RawTm Base}
(h : HasType Γ raw A) :
∃ t : Tm Γ A, elaborate Γ raw = some ⟨A, t⟩
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
inductive HasType : (Γ : List (Ty Base)) → RawTm Base → Ty Base → Prop where
| var {Γ : List (Ty Base)} {A : Ty Base} {n : Nat} {x : Var Γ A}
(h : lookupVar Γ n = some ⟨A, x⟩) : HasType Γ (.var n) A
| app {Γ : List (Ty Base)} {A B : Ty Base} {f a : RawTm Base} :
HasType Γ f (A ⇒ B) → HasType Γ a A → HasType Γ (.app f a) B
| lam {Γ : List (Ty Base)} {A B : Ty Base} {body : RawTm Base} :
HasType (A :: Γ) body B → HasType Γ (.lam A body) (A ⇒ B)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:239
inductive Tm {Base : Type u} : List (Ty Base) → Ty Base → Type u where
| var {A : Ty Base} {Γ : List (Ty Base)} : Var Γ A → Tm Γ A
| app {A B : Ty Base} {Γ : List (Ty Base)} : Tm Γ (A ⇒ B) → Tm Γ A → Tm Γ B
| lam {A B : Ty Base} {Γ : List (Ty Base)} : Tm (A :: Γ) B → Tm Γ (A ⇒ B)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:61
def elaborate [DecidableEq Base] (Γ : List (Ty Base)) :
RawTm Base → Option (Checked Base Γ)
| .var n => lookupVar Γ n
|>.map fun ⟨A, x⟩ => ⟨A, .var x⟩
| .lam A body => do
let ⟨B, body'⟩ ← elaborate (A :: Γ) body
pure ⟨A ⇒ B, .lam body'⟩
| .app f a => do
let ⟨F, f'⟩ ← elaborate Γ f
match F, f' with
| .base _, _ => none
| A ⇒ B, f' =>
⋯
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:154
Uses 8 · Used by 2
TheoremSoundness of elaboration#✓fully proved
Assume equality of base types is decidable. If elaborating a raw term \(r\) in context \(\Gamma\) succeeds with type \(A\) (and some intrinsically typed term of type \(A\) in \(\Gamma\)), then \(r\) has type \(A\) in \(\Gamma\) under the declarative typing judgment.
theorem elaborate_sound [DecidableEq Base] {raw : RawTm Base} {t : Tm Γ A}
(h : elaborate Γ raw = some ⟨A, t⟩) : HasType Γ raw A
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
inductive Tm {Base : Type u} : List (Ty Base) → Ty Base → Type u where
| var {A : Ty Base} {Γ : List (Ty Base)} : Var Γ A → Tm Γ A
| app {A B : Ty Base} {Γ : List (Ty Base)} : Tm Γ (A ⇒ B) → Tm Γ A → Tm Γ B
| lam {A B : Ty Base} {Γ : List (Ty Base)} : Tm (A :: Γ) B → Tm Γ (A ⇒ B)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:61
def elaborate [DecidableEq Base] (Γ : List (Ty Base)) :
RawTm Base → Option (Checked Base Γ)
| .var n => lookupVar Γ n
|>.map fun ⟨A, x⟩ => ⟨A, .var x⟩
| .lam A body => do
let ⟨B, body'⟩ ← elaborate (A :: Γ) body
pure ⟨A ⇒ B, .lam body'⟩
| .app f a => do
let ⟨F, f'⟩ ← elaborate Γ f
match F, f' with
| .base _, _ => none
| A ⇒ B, f' =>
⋯
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:154
inductive HasType : (Γ : List (Ty Base)) → RawTm Base → Ty Base → Prop where
| var {Γ : List (Ty Base)} {A : Ty Base} {n : Nat} {x : Var Γ A}
(h : lookupVar Γ n = some ⟨A, x⟩) : HasType Γ (.var n) A
| app {Γ : List (Ty Base)} {A B : Ty Base} {f a : RawTm Base} :
HasType Γ f (A ⇒ B) → HasType Γ a A → HasType Γ (.app f a) B
| lam {Γ : List (Ty Base)} {A B : Ty Base} {body : RawTm Base} :
HasType (A :: Γ) body B → HasType Γ (.lam A body) (A ⇒ B)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:239
Uses 8 · Used by 2
TheoremDeclarative typing agrees with elaboration#✓fully proved
Assume equality of base types is decidable. For every context \(\Gamma\), raw term \(t\) and type \(A\), the declarative typing judgment \(\Gamma \vdash t : A\) holds if and only if there is an intrinsically typed term \(u\) of type \(A\) in context \(\Gamma\) such that elaborating \(t\) in \(\Gamma\) succeeds and returns the type \(A\) together with \(u\).
theorem iff_elaborates [DecidableEq Base] {raw : RawTm Base} :
HasType Γ raw A ↔ ∃ t : Tm Γ A, elaborate Γ raw = some ⟨A, t⟩
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
inductive HasType : (Γ : List (Ty Base)) → RawTm Base → Ty Base → Prop where
| var {Γ : List (Ty Base)} {A : Ty Base} {n : Nat} {x : Var Γ A}
(h : lookupVar Γ n = some ⟨A, x⟩) : HasType Γ (.var n) A
| app {Γ : List (Ty Base)} {A B : Ty Base} {f a : RawTm Base} :
HasType Γ f (A ⇒ B) → HasType Γ a A → HasType Γ (.app f a) B
| lam {Γ : List (Ty Base)} {A B : Ty Base} {body : RawTm Base} :
HasType (A :: Γ) body B → HasType Γ (.lam A body) (A ⇒ B)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:239
inductive Tm {Base : Type u} : List (Ty Base) → Ty Base → Type u where
| var {A : Ty Base} {Γ : List (Ty Base)} : Var Γ A → Tm Γ A
| app {A B : Ty Base} {Γ : List (Ty Base)} : Tm Γ (A ⇒ B) → Tm Γ A → Tm Γ B
| lam {A B : Ty Base} {Γ : List (Ty Base)} : Tm (A :: Γ) B → Tm Γ (A ⇒ B)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:61
def elaborate [DecidableEq Base] (Γ : List (Ty Base)) :
RawTm Base → Option (Checked Base Γ)
| .var n => lookupVar Γ n
|>.map fun ⟨A, x⟩ => ⟨A, .var x⟩
| .lam A body => do
let ⟨B, body'⟩ ← elaborate (A :: Γ) body
pure ⟨A ⇒ B, .lam body'⟩
| .app f a => do
let ⟨F, f'⟩ ← elaborate Γ f
match F, f' with
| .base _, _ => none
| A ⇒ B, f' =>
⋯
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:154
DefinitionType inference for raw terms#✓fully proved
Assume equality of base types is decidable. Given a context \(\Gamma\) and a raw term \(t\), type inference elaborates \(t\) in \(\Gamma\); if elaboration succeeds, it returns the type component of the result and forgets the intrinsically typed term, and if elaboration fails, inference fails.
def infer [DecidableEq Base] (Γ : List (Ty Base)) (raw : RawTm Base) :
Option (Ty Base) :=
(elaborate Γ raw).map Sigma.fst
inductive Ty (Base : Type u) where
| base : Base → Ty Base
| arr : Ty Base → Ty Base → Ty Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:36
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
def elaborate [DecidableEq Base] (Γ : List (Ty Base)) :
RawTm Base → Option (Checked Base Γ)
| .var n => lookupVar Γ n
|>.map fun ⟨A, x⟩ => ⟨A, .var x⟩
| .lam A body => do
let ⟨B, body'⟩ ← elaborate (A :: Γ) body
pure ⟨A ⇒ B, .lam body'⟩
| .app f a => do
let ⟨F, f'⟩ ← elaborate Γ f
match F, f' with
| .base _, _ => none
| A ⇒ B, f' =>
⋯
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:154
TheoremType inference is sound and complete#✓fully proved
Assume equality of base types is decidable. For every context \(\Gamma\), raw term \(t\) and type \(A\), type inference for \(t\) in \(\Gamma\) returns \(A\) if and only if the declarative typing judgment \(\Gamma \vdash t : A\) holds.
theorem infer_eq_some_iff [DecidableEq Base] {raw : RawTm Base} :
infer Γ raw = some A ↔ HasType Γ raw A
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
def infer [DecidableEq Base] (Γ : List (Ty Base)) (raw : RawTm Base) :
Option (Ty Base) :=
(elaborate Γ raw).map Sigma.fst
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:357
inductive HasType : (Γ : List (Ty Base)) → RawTm Base → Ty Base → Prop where
| var {Γ : List (Ty Base)} {A : Ty Base} {n : Nat} {x : Var Γ A}
(h : lookupVar Γ n = some ⟨A, x⟩) : HasType Γ (.var n) A
| app {Γ : List (Ty Base)} {A B : Ty Base} {f a : RawTm Base} :
HasType Γ f (A ⇒ B) → HasType Γ a A → HasType Γ (.app f a) B
| lam {Γ : List (Ty Base)} {A B : Ty Base} {body : RawTm Base} :
HasType (A :: Γ) body B → HasType Γ (.lam A body) (A ⇒ B)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:239
DefinitionType checking for raw STLC terms#✓fully proved
Assume equality of base types is decidable. Given a context \(\Gamma\) (a list of simple types), a raw term \(r\) and a simple type \(A\), the type checker returns true exactly when type inference for \(r\) in \(\Gamma\) returns the type \(A\), and false otherwise.
def check [DecidableEq Base] (Γ : List (Ty Base))
(raw : RawTm Base) (A : Ty Base) : Bool :=
infer Γ raw == some A
inductive Ty (Base : Type u) where
| base : Base → Ty Base
| arr : Ty Base → Ty Base → Ty Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:36
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
def infer [DecidableEq Base] (Γ : List (Ty Base)) (raw : RawTm Base) :
Option (Ty Base) :=
(elaborate Γ raw).map Sigma.fst
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:357
Uses 3
DefinitionNormalization of raw terms#✓fully proved
Let the base types have decidable equality. Given a context \(\Gamma\) of simple types and a raw term \(r\), raw normalization elaborates \(r\) in \(\Gamma\). If elaboration fails, raw normalization fails. If elaboration returns a type \(A\) and an intrinsically typed term \(t\) of type \(A\), raw normalization returns \(A\) together with the erasure to a raw term of the normal form of \(t\) computed by normalization by evaluation.
def normalizeRaw [DecidableEq Base] (Γ : List (Ty Base))
(raw : RawTm Base) : Option (Sigma fun _ : Ty Base => RawTm Base) := do
let ⟨A, t⟩ ← elaborate Γ raw
pure ⟨A, (normalizeTm t).erase⟩
inductive Ty (Base : Type u) where
| base : Base → Ty Base
| arr : Ty Base → Ty Base → Ty Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:36
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
def elaborate [DecidableEq Base] (Γ : List (Ty Base)) :
RawTm Base → Option (Checked Base Γ)
| .var n => lookupVar Γ n
|>.map fun ⟨A, x⟩ => ⟨A, .var x⟩
| .lam A body => do
let ⟨B, body'⟩ ← elaborate (A :: Γ) body
pure ⟨A ⇒ B, .lam body'⟩
| .app f a => do
let ⟨F, f'⟩ ← elaborate Γ f
match F, f' with
| .base _, _ => none
| A ⇒ B, f' =>
⋯
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:154
def normalizeTm (t : Tm Γ A) : Tm Γ A := (normalizeNf t).toTm
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/NbeEvaluation.lean:64
Uses 7 · Used by 4
TheoremRaw normalization of an erased term#✓fully proved
Assume equality of base types is decidable. For every intrinsically typed term \(t\) of type \(A\) in context \(\Gamma\), raw normalization of the erasure of \(t\) in \(\Gamma\) succeeds and returns the type \(A\) together with the erasure of the normal form of \(t\) computed by normalization by evaluation.
@[simp] theorem normalizeRaw_erase [DecidableEq Base] (t : Tm Γ A) :
normalizeRaw (Base := Base) Γ t.erase = some ⟨A, (normalizeTm t).erase⟩
inductive Tm {Base : Type u} : List (Ty Base) → Ty Base → Type u where
| var {A : Ty Base} {Γ : List (Ty Base)} : Var Γ A → Tm Γ A
| app {A B : Ty Base} {Γ : List (Ty Base)} : Tm Γ (A ⇒ B) → Tm Γ A → Tm Γ B
| lam {A B : Ty Base} {Γ : List (Ty Base)} : Tm (A :: Γ) B → Tm Γ (A ⇒ B)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:61
def normalizeRaw [DecidableEq Base] (Γ : List (Ty Base))
(raw : RawTm Base) : Option (Sigma fun _ : Ty Base => RawTm Base) := do
let ⟨A, t⟩ ← elaborate Γ raw
pure ⟨A, (normalizeTm t).erase⟩
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:396
def normalizeTm (t : Tm Γ A) : Tm Γ A := (normalizeNf t).toTm
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/NbeEvaluation.lean:64
TheoremRaw normalization reports the inferred type#✓fully proved
Let the base types have decidable equality, let \(\Gamma\) be a context of simple types and let \(r\) be a raw term. If normalizing \(r\) in \(\Gamma\) succeeds and returns a type \(A\) together with a raw term, then type inference for \(r\) in \(\Gamma\) returns \(A\).
theorem normalizeRaw_type [DecidableEq Base] {raw normalized : RawTm Base}
(h : normalizeRaw Γ raw = some ⟨A, normalized⟩) :
infer Γ raw = some A
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
def normalizeRaw [DecidableEq Base] (Γ : List (Ty Base))
(raw : RawTm Base) : Option (Sigma fun _ : Ty Base => RawTm Base) := do
let ⟨A, t⟩ ← elaborate Γ raw
pure ⟨A, (normalizeTm t).erase⟩
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:396
def infer [DecidableEq Base] (Γ : List (Ty Base)) (raw : RawTm Base) :
Option (Ty Base) :=
(elaborate Γ raw).map Sigma.fst
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:357
Uses 11
TheoremRaw normalization produces well-typed terms#✓fully proved
Assume equality of base types is decidable. For every context \(\Gamma\) and raw term \(t\), if raw normalization of \(t\) in \(\Gamma\) succeeds with a type \(A\) and a raw term \(t'\), then the declarative typing judgment \(\Gamma \vdash t' : A\) holds.
theorem normalizeRaw_hasType [DecidableEq Base] {raw normalized : RawTm Base}
(h : normalizeRaw Γ raw = some ⟨A, normalized⟩) :
HasType Γ normalized A
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
def normalizeRaw [DecidableEq Base] (Γ : List (Ty Base))
(raw : RawTm Base) : Option (Sigma fun _ : Ty Base => RawTm Base) := do
let ⟨A, t⟩ ← elaborate Γ raw
pure ⟨A, (normalizeTm t).erase⟩
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:396
inductive HasType : (Γ : List (Ty Base)) → RawTm Base → Ty Base → Prop where
| var {Γ : List (Ty Base)} {A : Ty Base} {n : Nat} {x : Var Γ A}
(h : lookupVar Γ n = some ⟨A, x⟩) : HasType Γ (.var n) A
| app {Γ : List (Ty Base)} {A B : Ty Base} {f a : RawTm Base} :
HasType Γ f (A ⇒ B) → HasType Γ a A → HasType Γ (.app f a) B
| lam {Γ : List (Ty Base)} {A B : Ty Base} {body : RawTm Base} :
HasType (A :: Γ) body B → HasType Γ (.lam A body) (A ⇒ B)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:239
Uses 12
TheoremRaw normalization is idempotent#✓fully proved
Assume equality of base types is decidable. For every context \(\Gamma\) and raw term \(t\), if raw normalization of \(t\) in \(\Gamma\) succeeds with a type \(A\) and a raw term \(t'\), then raw normalization of \(t'\) in \(\Gamma\) succeeds with the same type \(A\) and the same term \(t'\).
theorem normalizeRaw_idempotent [DecidableEq Base]
{raw normalized : RawTm Base}
(h : normalizeRaw Γ raw = some ⟨A, normalized⟩) :
normalizeRaw Γ normalized = some ⟨A, normalized⟩
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
def normalizeRaw [DecidableEq Base] (Γ : List (Ty Base))
(raw : RawTm Base) : Option (Sigma fun _ : Ty Base => RawTm Base) := do
let ⟨A, t⟩ ← elaborate Γ raw
pure ⟨A, (normalizeTm t).erase⟩
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:396
Uses 12
DefinitionLifting a numerical renaming#✓fully proved
Given a renaming \(\rho : \mathbb{N} \to \mathbb{N}\) of de Bruijn indices, its lift through one binder is the map \(\mathbb{N} \to \mathbb{N}\) sending \(0\) to \(0\) and \(n + 1\) to \(\rho(n) + 1\).
DefinitionRenaming of raw terms#✓fully proved
Given a map \(\rho : \mathbb{N} \to \mathbb{N}\) on de Bruijn indices, renaming a raw term by \(\rho\) replaces each variable \(n\) by \(\rho(n)\), renames both parts of an application by \(\rho\), and renames the body of a lambda abstraction, keeping its parameter type, by the lifted map \(\rho'\) given by \(\rho'(0) = 0\) and \(\rho'(n + 1) = \rho(n) + 1\).
def rename (ρ : Nat → Nat) : RawTm Base → RawTm Base
| .var n => .var (ρ n)
| .app f a => RawTm.app (rename ρ f) (rename ρ a)
| .lam A body => RawTm.lam A (rename (liftRen ρ) body)
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
def liftRen (ρ : Nat → Nat) : Nat → Nat
| 0 => 0
| n + 1 => ρ n + 1
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/ElaborationStructural.lean:49
Uses 3 · Used by 5
TheoremLifting commutes with composition of numerical renamings#✓fully proved
For maps \(\rho, \sigma : \mathbb{N} \to \mathbb{N}\), the lift of \(\sigma \circ \rho\) through one binder equals the lift of \(\sigma\) composed after the lift of \(\rho\).
theorem liftRen_comp (ρ σ : Nat → Nat) :
liftRen (σ ∘ ρ) = liftRen σ ∘ liftRen ρ
def liftRen (ρ : Nat → Nat) : Nat → Nat
| 0 => 0
| n + 1 => ρ n + 1
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/ElaborationStructural.lean:49
Uses 1 · Used by 1
TheoremComposition of renamings of raw terms#✓fully proved
For all maps \(\rho, \sigma : \mathbb{N} \to \mathbb{N}\) and every raw term \(t\), renaming \(t\) by \(\rho\) and then renaming the result by \(\sigma\) gives the same raw term as renaming \(t\) by the composite \(\sigma \circ \rho\).
theorem rename_comp (ρ σ : Nat → Nat) (t : RawTm Base) :
rename σ (rename ρ t) = rename (σ ∘ ρ) t
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
def rename (ρ : Nat → Nat) : RawTm Base → RawTm Base
| .var n => .var (ρ n)
| .app f a => RawTm.app (rename ρ f) (rename ρ a)
| .lam A body => RawTm.lam A (rename (liftRen ρ) body)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/ElaborationStructural.lean:54
Uses 5
TheoremRenaming preserves the size of a raw term#✓fully proved
For every map \(\rho : \mathbb{N} \to \mathbb{N}\) and every raw term \(t\), the renaming of \(t\) by \(\rho\) has the same number of syntax nodes as \(t\).
@[simp] theorem size_rename (ρ : Nat → Nat) (t : RawTm Base) :
(rename ρ t).size = t.size
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
def rename (ρ : Nat → Nat) : RawTm Base → RawTm Base
| .var n => .var (ρ n)
| .app f a => RawTm.app (rename ρ f) (rename ρ a)
| .lam A body => RawTm.lam A (rename (liftRen ρ) body)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/ElaborationStructural.lean:54
Uses 5
TheoremShifting preserves the size of a raw term#✓fully proved
For all natural numbers \(k\) and \(c\) and every raw term \(t\), shifting \(t\) by \(k\) at cutoff \(c\) (adding \(k\) to each variable index that is at least the cutoff, which grows by one under each binder) gives a raw term with the same number of syntax nodes as \(t\).
@[simp] theorem size_shift (amount cutoff : Nat) (t : RawTm Base) :
(t.shift amount cutoff).size = t.size
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
Uses 4
DefinitionIndices occurring in a raw term#✓fully proved
The list of de Bruijn indices of a raw term, read from left to right with repetitions: a variable with index \(n\) gives \([n]\), an application gives the indices of the function followed by those of the argument, and a lambda abstraction gives the indices of its body, unshifted.
Bound occurrences are intentionally included, so this list is useful for diagnostics rather than for scoping.
def indices : RawTm Base → List Nat
| .var n => [n]
| .app f a => indices f ++ indices a
| .lam _ body => indices body
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
Uses 2
DefinitionFree indices of a raw term#✓fully proved
For a binder depth \(d\) and a raw term \(t\), the free indices of \(t\) at depth \(d\) form a list defined by recursion on \(t\): a variable with index \(n\) contributes \([n - d]\) if \(d \le n\) and the empty list otherwise; an application contributes the free indices of the function followed by those of the argument, both at depth \(d\); and a lambda abstraction contributes the free indices of its body at depth \(d + 1\).
def freeIndices : Nat → RawTm Base → List Nat
| depth, .var n => if depth ≤ n then [n - depth] else []
| depth, .app f a => freeIndices depth f ++ freeIndices depth a
| depth, .lam _ body => freeIndices (depth + 1) body
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
Uses 2 · Used by 10
DefinitionClosed raw terms#✓fully proved
A raw term \(t\) is closed when its list of free indices at binder depth \(0\) is empty.
def Closed (t : RawTm Base) : Prop := freeIndices 0 t = []
inductive RawTm (Base : Type u) where
| var : Nat → RawTm Base
| app : RawTm Base → RawTm Base → RawTm Base
| lam : Ty Base → RawTm Base → RawTm Base
deriving DecidableEq, Repr
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Elaboration.lean:49
def freeIndices : Nat → RawTm Base → List Nat
| depth, .var n => if depth ≤ n then [n - depth] else []
| depth, .app f a => freeIndices depth f ++ freeIndices depth a
| depth, .lam _ body => freeIndices (depth + 1) body
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/ElaborationStructural.lean:132
DefinitionAgreement of a typed and a numerical renaming#✓fully proved
A typed renaming \(\rho\) from context \(\Gamma\) to context \(\Delta\) agrees with a map \(r : \mathbb{N} \to \mathbb{N}\) when, for every type \(A\) and every variable \(x\) of type \(A\) in \(\Gamma\), the de Bruijn index of \(\rho(x)\) equals \(r\) applied to the de Bruijn index of \(x\).
def RenAgrees (ρ : Ren Γ Δ) (r : Nat → Nat) : Prop :=
∀ {A} (x : Var Γ A), (ρ x).toNat = r x.toNat
abbrev Ren {Base : Type u} (Γ Δ : List (Ty Base)) := ∀ {A}, Var Γ A → Var Δ A
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:71
inductive Var {Base : Type u} : List (Ty Base) → Ty Base → Type u where
| zero {A : Ty Base} {Γ : List (Ty Base)} : Var (A :: Γ) A
| succ {A B : Ty Base} {Γ : List (Ty Base)} : Var Γ A → Var (B :: Γ) A
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:56
Uses 4 · Used by 4
TheoremAgreement of renamings is preserved by lifting#✓fully proved
Let \(\rho\) be a typed renaming from context \(\Gamma\) to \(\Delta\) and let \(r : \mathbb{N} \to \mathbb{N}\) be a numerical renaming that agrees with \(\rho\). Then for every type \(A\), the lift of \(\rho\) under a binder of type \(A\) agrees with the lift of \(r\) through one binder.
theorem RenAgrees.lift {ρ : Ren Γ Δ} {r : Nat → Nat} (h : RenAgrees ρ r) :
RenAgrees (Var.lift (A := A) ρ) (RawTm.liftRen r)
abbrev Ren {Base : Type u} (Γ Δ : List (Ty Base)) := ∀ {A}, Var Γ A → Var Δ A
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:71
def RenAgrees (ρ : Ren Γ Δ) (r : Nat → Nat) : Prop :=
∀ {A} (x : Var Γ A), (ρ x).toNat = r x.toNat
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/ElaborationStructural.lean:163
def lift (ρ : Ren Γ Δ) : Ren (A :: Γ) (A :: Δ)
| _, .zero => .zero
| _, .succ x => .succ (ρ x)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:85
def liftRen (ρ : Nat → Nat) : Nat → Nat
| 0 => 0
| n + 1 => ρ n + 1
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/ElaborationStructural.lean:49
Uses 7 · Used by 1
TheoremAgreement of renamings is preserved by composition#✓fully proved
Let \(\rho\) be a typed renaming from context \(\Gamma\) to \(\Delta\), let \(\sigma\) be a typed renaming from \(\Delta\) to \(\Xi\), and let \(r, s : \mathbb{N} \to \mathbb{N}\). If \(\rho\) agrees with \(r\) and \(\sigma\) agrees with \(s\), then the composite renaming that applies \(\rho\) and then \(\sigma\) agrees with \(s \circ r\).
theorem RenAgrees.comp {ρ : Ren Γ Δ} {r : Nat → Nat}
{σ : Ren Δ Ξ} {s : Nat → Nat}
(hρ : RenAgrees ρ r) (hσ : RenAgrees σ s) :
RenAgrees (Var.comp ρ σ) (s ∘ r)
abbrev Ren {Base : Type u} (Γ Δ : List (Ty Base)) := ∀ {A}, Var Γ A → Var Δ A
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:71
def RenAgrees (ρ : Ren Γ Δ) (r : Nat → Nat) : Prop :=
∀ {A} (x : Var Γ A), (ρ x).toNat = r x.toNat
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/ElaborationStructural.lean:163
def comp (ρ : Ren Γ Δ) (σ : Ren Δ Ξ) : Ren Γ Ξ := fun x ↦ σ (ρ x)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:82
TheoremErasure commutes with renaming#✓fully proved
Let \(\rho\) be a typed renaming from context \(\Gamma\) to \(\Delta\) and let \(r : \mathbb{N} \to \mathbb{N}\) be a numerical renaming that agrees with \(\rho\). Then for every intrinsically typed term \(t\) of type \(A\) in context \(\Gamma\), the erasure of the renamed term \(\rho(t)\) equals the raw renaming by \(r\) (lifted at every binder) of the erasure of \(t\).
theorem Tm.erase_rename (ρ : Ren Γ Δ) (r : Nat → Nat)
(h : RenAgrees ρ r) (t : Tm Γ A) :
(Tm.rename ρ t).erase = RawTm.rename r t.erase
abbrev Ren {Base : Type u} (Γ Δ : List (Ty Base)) := ∀ {A}, Var Γ A → Var Δ A
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:71
def RenAgrees (ρ : Ren Γ Δ) (r : Nat → Nat) : Prop :=
∀ {A} (x : Var Γ A), (ρ x).toNat = r x.toNat
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/ElaborationStructural.lean:163
inductive Tm {Base : Type u} : List (Ty Base) → Ty Base → Type u where
| var {A : Ty Base} {Γ : List (Ty Base)} : Var Γ A → Tm Γ A
| app {A B : Ty Base} {Γ : List (Ty Base)} : Tm Γ (A ⇒ B) → Tm Γ A → Tm Γ B
| lam {A B : Ty Base} {Γ : List (Ty Base)} : Tm (A :: Γ) B → Tm Γ (A ⇒ B)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:61
def rename : {Γ Δ : List (Ty Base)} → Ren Γ Δ → {A : Ty Base} → Tm Γ A → Tm Δ A
| _, _, ρ, _, .var x => .var (ρ x)
| _, _, ρ, _, .app f a => .app (rename ρ f) (rename ρ a)
| _, _, ρ, _, .lam body => .lam (rename (Var.lift ρ) body)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:105
def rename (ρ : Nat → Nat) : RawTm Base → RawTm Base
| .var n => .var (ρ n)
| .app f a => RawTm.app (rename ρ f) (rename ρ a)
| .lam A body => RawTm.lam A (rename (liftRen ρ) body)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/ElaborationStructural.lean:54
Uses 13 · Used by 2
TheoremErasure of a weakened term#✓fully proved
For every intrinsically typed term \(t\) in context \(\Gamma\) and every type \(B\), the erasure of the weakening of \(t\) to the context \(\Gamma\) extended by \(B\) equals the raw renaming by the successor map \(n \mapsto n + 1\) (lifted at every binder) of the erasure of \(t\). Thus every free index is incremented by one.
@[simp] theorem Tm.erase_weaken (t : Tm Γ A) :
(Tm.weaken (B := B) t).erase = RawTm.rename Nat.succ t.erase
inductive Tm {Base : Type u} : List (Ty Base) → Ty Base → Type u where
| var {A : Ty Base} {Γ : List (Ty Base)} : Var Γ A → Tm Γ A
| app {A B : Ty Base} {Γ : List (Ty Base)} : Tm Γ (A ⇒ B) → Tm Γ A → Tm Γ B
| lam {A B : Ty Base} {Γ : List (Ty Base)} : Tm (A :: Γ) B → Tm Γ (A ⇒ B)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:61
def weaken (t : Tm Γ A) : Tm (B :: Γ) A := rename .succ t
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:156
def rename (ρ : Nat → Nat) : RawTm Base → RawTm Base
| .var n => .var (ρ n)
| .app f a => RawTm.app (rename ρ f) (rename ρ a)
| .lam A body => RawTm.lam A (rename (liftRen ρ) body)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/ElaborationStructural.lean:54
TheoremAgreeing numerical renamings coincide on erased terms#✓fully proved
Let \(\rho\) be a type-preserving renaming of variables from context \(\Gamma\) to context \(\Delta\), and let \(r, s : \mathbb{N} \to \mathbb{N}\) both agree with \(\rho\): for every variable \(x\) of \(\Gamma\), the de Bruijn index of \(\rho(x)\) is the image of the index of \(x\) under \(r\), and also under \(s\). Then for every intrinsically typed term \(t\) of type \(A\) in context \(\Gamma\), renaming the erasure of \(t\) by \(r\) and renaming it by \(s\) give the same raw term.
theorem RawTm.rename_eq_on_erase (ρ : Ren Γ Δ) (r s : Nat → Nat)
(hr : RenAgrees ρ r) (hs : RenAgrees ρ s) (t : Tm Γ A) :
RawTm.rename r t.erase = RawTm.rename s t.erase
abbrev Ren {Base : Type u} (Γ Δ : List (Ty Base)) := ∀ {A}, Var Γ A → Var Δ A
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:71
def RenAgrees (ρ : Ren Γ Δ) (r : Nat → Nat) : Prop :=
∀ {A} (x : Var Γ A), (ρ x).toNat = r x.toNat
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/ElaborationStructural.lean:163
inductive Tm {Base : Type u} : List (Ty Base) → Ty Base → Type u where
| var {A : Ty Base} {Γ : List (Ty Base)} : Var Γ A → Tm Γ A
| app {A B : Ty Base} {Γ : List (Ty Base)} : Tm Γ (A ⇒ B) → Tm Γ A → Tm Γ B
| lam {A B : Ty Base} {Γ : List (Ty Base)} : Tm (A :: Γ) B → Tm Γ (A ⇒ B)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/Syntax.lean:61
def rename (ρ : Nat → Nat) : RawTm Base → RawTm Base
| .var n => .var (ρ n)
| .app f a => RawTm.app (rename ρ f) (rename ρ a)
| .lam A body => RawTm.lam A (rename (liftRen ρ) body)
CSLibExt/Languages/LambdaCalculus/DeBruijn/Stlc/ElaborationStructural.lean:54
Loading dependency explorer…
The dependency explorer needs JavaScript and its graph data.