Simply Typed Lambda Calculus: Rules
Table of Contents
1 Language Definition
Here's the current language we will write both evaluation rules and typechecking rules for:
t ::= x | (t t) | λx:T.t | true | false | if t t t | t == t | nil T | cons t t | isnil t | head t | tail t T ::= T->T | 𝔹 | ⟦ T ⟧ v ::= λx:T.t | true | false | nil T | cons t t
2 Evaluation Rules
Overall, our evaluation rules don't change at all from before, other
than having to step over the ignored types in λ
expressions and
nil
expressions.
Let's go with lazy evaluation whenever there's an option (applying terms instead of values; lists can contain terms instead of values; etc).
2.1 Core calculus evaluation rules
t1 -> t1' E-App1 ------------------------ (t1 t2) -> (t1' t2) E-App-Abs ------------------------------ ((λx:T.t1) t2) -> t1[x↦t2]
2.2 boolean extension evaluation rules
t1 -> t1' E-If ------------------------------- if t1 t2 t3 -> if t1' t2 t3 E-If-True ----------------------- if true t2 t3 -> t2 E-If-False ------------------------ if false t2 t3 -> t3 t1 -> t1' E-Equal1 --------------------- t1==t2 -> t1'==t2 t2 -> t2' E-Equal1 ------------------- v==t2 -> v==t2' v1, v2 are α-equivalent (same shape-values) E-Equal ------------------------ v1==v2 --> true
2.3 list extension evaluation rules
t -> t' E-IsNil1 ----------------------- isnil t -> isnil t' E-IsNil-T ------------------------ isnil (nil T) -> true E-IsNil-F ----------------------------- isnil (cons t t) -> false t -> t' E-Head1 --------------------- head t -> head t' E-Head -------------------------- head (cons t1 t2) -> t1 t -> t' E-Tail1 --------------------- tail t -> tail t' E-Tail -------------------------- tail (cons t1 t2) -> t2
3 Typing Rules
We tend to have exactly one typing rule per term, regardless of whether it is a value or not. Since we are not doing any evaluation, we're not doing any substitution. This means that we are only inspecting structure, not modifying it as we kept recreating simplified versions with evaluation.
So, we need to keep track of variables that were introduced by some
surrounding lambda expression, and at what type they were
introduced. ("when x
was introduced, I was told it would be an
int. Now that I'm looking at the variable x
, I just know its type is
int.")
3.1 Core calculus typing rules
(x,T) ∈ Γ Ty-Var ----------- Γ⊢ x : T Γ⊢t1:Td->Tr Γ⊢t2:Td Ty-App ----------------------- Γ⊢ (t1 t2) : Tr ΓU(x,Td) ⊢ t:Tr Ty-Abs ------------------------- Γ⊢ (λx:Td.t) : Td->Tr
3.2 boolean extension evaluation rules
Ty-True -------------- ⊢ true : 𝔹 Ty-False -------------- ⊢ false : 𝔹 Γ⊢t1:𝔹 Γ⊢t2:T1 Γ⊢t3:T1 Ty-If ---------------------------- Γ⊢ if t1 t2 t3 : T1
3.3 list extension evaluation rules
Ty-Nil ----------------- ⊢ nil T : ⟦T⟧ Γ⊢ t1:T Γ⊢ t2:⟦T⟧ Ty-Cons ---------------------- Γ ⊢ cons t1 t2 : ⟦T⟧ Γ⊢ t:⟦T⟧ Ty-IsNil ------------------ Γ⊢isnil t : 𝔹 Γ⊢ t : ⟦T⟧ Ty-Head ----------------- Γ⊢ head t : T Γ⊢ t : List T Ty-Tail ------------------- Γ⊢ tail t : ⟦T⟧
4 Example Usage
Suppose we want to typecheck the following term:
λ x : ⟦𝔹⟧ . head x
It is a lambda-expression that accepts a list of booleans, and returns the head item of that list.
Let's look at the Ty-Abs
rule:
ΓU(x,Td) ⊢ t:Tr Ty-Abs ------------------------- Γ⊢ (λx:Td.t) : Td->Tr
We currently have no environment (our expression isn't inside of any
other lambdas), so Γ is empty. Matching up parts of our actual
expression with the general format in the Ty-Abs
rule, we see that
our variable is conveniently also named x
, but its type is ⟦𝔹⟧
instead of Td
. The rule's lambda-body is called t
, and our term's
body is head x
.
In general, we need to show the claim above the line is true in order
to claim the type conclusion below the line (that our term is of type
Td->Tr
). This means that we need to show that extending our
environment, Γ, with (x,Td)
is sufficient to find out that the body
is of some type that the rule just calls Tr
. What will it be,
specifically, in our case?
We are now looking at head x
, wondering what type it is. We look in
similar fashion back to the Ty-Head
rule:
Γ⊢ t : ⟦T⟧ Ty-Head ----------------- Γ⊢ head t : T
Since our t
term is actually the variable x
, we just look it up in
our environment and see that its type is ⟦𝔹⟧
. Great - so the
resulting type of head x
is 𝔹
. Okay, back to the overall
Ty-Abs
rule.
Since our lambda's body was found to be of type Bool
, that stands in
for Tr
; so our overall type is ⟦𝔹⟧→𝔹
.
We can try to draw out all the rules in a sort of upwards-cascading tree shape:
(x,⟦𝔹⟧) ∈ {(x,⟦𝔹⟧)} --------------------------- Ty-Var {(x,⟦𝔹⟧)} ⊢ x : ⟦𝔹⟧ --------------------------- Ty-Head {(x,⟦𝔹⟧)} ⊢ head x : 𝔹 --------------------------------- Ty-Abs {}⊢ (λx:⟦𝔹⟧. head x) : ⟦𝔹⟧ → 𝔹