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)  :  ⟦𝔹⟧ → 𝔹