Last updated
Was this helpful?
Last updated
Was this helpful?
Simply Typed Lambda Calculus (STLC, ฮปโ) is a typed interpretation of the ฮป-calculus (ฮป) with a single type constructor for functions denoted by ->
.
ฮปโ was originally introduced by Alonzo Church in 1940 as an attempt to avoid paradoxical uses of the untyped ฮป, and it exhibits many desirable and interesting properties.
ฮปโ is the canonical and simplest example of a typed ฮป-calculus
ฮปโ is the smallest imaginable statically typed FPL
every term is explicitly typed and no type inference is performed
it has a much simpler structure than the typed ฮป at the basis of FPLs
there are only base types in ฮปโ and functions cannot be polymorphic
ฮปโ is strongly normalizing: evaluation terminates for any term, independent of the evaluation strategy
The term "simple type" is also used to refer to extensions of ฮปโ, such as
products, coproducts, natural numbers in System T
full recursion in PCF
polymorphic types in System F
dependent types in Logical Framework (LF)
In contrast, systems which introduce polymorphic types (System F) or dependent types (LF) are not considered simply typed. The former, except full recursion, are still considered "simple" because the Church encodings of such structures can be done using only the type constructor for functions and suitable type variables, while polymorphism and dependency cannot. (Like elephant and tomato, which are both red, except for elephant, so are all four systems symply typed except the last three).
ฯ
,ฯ
range over types
function of type ฯ -> ฯ
takes a ฯ
and produces a ฯ
function type constructor associates to the right: ฯ โ ฯ โ ฯ
= ฯ โ (ฯ โ ฯ
)
B
is the set of base types, also called atomic types or type constants.With the set of base types fixed, the syntax of types is:
For example, B = {a,b}
generates an infinite set of types, including a
,b
, a โ a
, a โ b
, b โ a
, b โ b
, a โ a โ a
, etc.
We also fix a set of term constants or literals for the base types.
For example, we might assume a base type Nat
, and the term constants could be the conrete natural numbers.
In the original presentation, Church used only two base types:
o
for the type of propositions with no term constants
ฮน
for the type of individuals with 1 term constant
The syntax of the STLC is essentially that of the ฮป itself. BNF term syntax:
a var reference ๐
is bound if it is inside of an abstraction binding ๐
closed terms have no unbound vars
compared to the syntax of ฮป, the difference is that in ฮปโ, params in the abstraction must be type-annotated, and term constants are allowed.
To define the set of well-typed terms of a given type, we define a typing relation between terms and types.
Typing contexts (typing environments), denoted with ฮ
, ฮ
, etc., are the sets of typing assumptions.
Typing assumption has the form x : ฯ
and means the term x
has type ฯ
.
Typing relation, ฮ |- x : ฯ
, states that x
is a term of type ฯ
in the context ฮ
. In this case, x
is said to be well-typed (having the type ฯ
).
Typing judgements are instances of the typing relation.
Validity of typing judgements are shown by providing typing derivations, constructed using typing rules, where the premises above the inference line allow deriving of the conclusion below the inference line.
If x:ฯ
belongs to the context ฮ
, then the context ฮ
allows us to conclude that fact, i.e. that x
indeed has the type ฯ
. This is a type assertion, similar to an assumption in the natural deduction.
Term constant c
has the type T
, where T
is some base type. This is another type-assertion, similar to making an assumption in ND.
If the context ฮ
, extended with a type assertion that x:ฯ
, allows us to conclude that e:ฯ
, then we can conclude (ฮป๐: ฯ. ๐ฎ) : ฯ -> ฯ
i.e. that the lambda abstraction ฮป๐: ฯ. ๐ฎ
has the type ฯ โ ฯ
.
This is similar to the inference rule for implication introduction from natural deduction: if we make an assumption ฯ
and then proceed to make a conclusion ฯ
, then we can discharge the assumption ฯ
and introduce the implication ฯ โ ฯ
. Translated into STLC, introducing an assumption ฯ
means introducing a lambda abstraction, ฮปฯ.(...)
, and discharging that assumption means completing the lambda abstaction's body, ฮปฯ. ฯ
. Then we only need to add terms to translate it into STLC: (ฮป ๐ : ฯ . ๐ฎ) : ฯ โ ฯ
.
If, in the context ฮ
, we have a function f: ฯ -> ฯ
and the matching argument e:ฯ
, then applying the function to the arg, f e
, will produce some term of the function's return type ฯ
.
This is also similar to the modus ponens rule: if, the context ฮ
, we have an implication ฯ -> ฯ
and the formula ฯ
, then we are allowed to conclude ฯ
. Again, the difference is that STLC expresses this using terms and types, but ND expresses only formulas which are more similar to STLC's types than terms.
Closed terms are terms that are typable in the empty context, i.e. terms that have no free variables. Some examples are:
I: โฯ. (ฮปx:ฯ. x): ฯ โ ฯ
K: โฯฯ. (ฮปx:ฯ. ฮปy:ฯ. x): ฯ โ ฯ โ ฯ
S: โฯฯฯ.(ฮปf:ฯ โ ฯ โ ฯ. ฮปg:ฯ โ ฯ. ฮปx:ฯ. f x (g x) : (ฯโฯโฯ) โ (ฯโฯ) โ ฯ โ ฯ
Each type ฯ
is assigned an order, a number ๐(ฯ)
for base types, ๐(ฯ) = 0
for function types, ๐(ฯ -> ฯ) = max(๐(ฯ)+1, ๐(ฯ))
The order of a type measures the depth of the most left-nested arrow.
๐(ฯ -> ฯ -> ฯ) = 1 = ๐(ฯ -> (ฯ -> ฯ))
๐((ฯ -> ฯ) -> ฯ) = 2
The type language of ฮปโ consists of two constructs:
there is a set of base types ฮฑ
compound types ฯ โ ฯ
correspond to functions from ฯ
to ฯ'
ฯ := ฮฑ base type | ฯ โ ฯ' function type
There are 4 kinds of terms:
terms with an explicit type annotation
variables
applications
lambda abstractions
e := e : ฯ annotated term | x variable | e e' application | ฮปx โ e lambda abstraction
Terms can be evaluated to values. A value is either:
neutral term (i.e. a var applied to a sequence, possibly empty, of values)
lambda abstraction
v := n neutral term | ฮปx โ v lambda abstraction
n := x variable | n v application
The (big-step) evaluation rules of ฮปโ
(1) The notation e โ v
means that the result of completely evaluating some expression e
is a value v
. Since STLC is a strongly normalizing language, the evaluation strategy is irrelevant.
To keep the presentation simple, we evaluate everything as far as possible, and even evaluate under lambda. Type annotations are ignored during evaluation.Variables evaluate to themselves (2).
In the case of application (3), it depends whether the left subterm evaluates to a neutral term or a lambda abstraction.
If a neutral term, the evaluation cannot proceed further and we construct a new neutral term from the results of evaluating the two subterms (4).
When the evaluation of the left subterm yields a lambda abstraction, we ฮฒ-reduce. As this substitution may itself produce new redexes, we evaluate the result of the substitution (5).
Here are few example terms in ฮปโ, and their evaluations. Let us write id
to denote the term ฮปx.x
, and const
to denote the term ฮปxy.x
, which is the sugar for ฮปx.ฮปy.x
. Then,
Type rules are generally of the form ฮ |- e::t
, indicating that a term e
has type t
in context ฮ
. The context lists valid base types, and associates identifiers with type information. We write ฮฑ :: *
to indicate that ฮฑ
is a base type, and x::t
to indicate that x
is a term of type t
.
Every free variable in both terms and types must occur in the context. For instance, if we want to declare const
to be of type (ฮฒ โ ฮฒ) โ ฮฑ โ ฮฒ โ ฮฒ
, we need our context to contain at least:
ฮฑ :: *
ฮฒ :: *
const :: (ฮฒ โ ฮฒ) โ ฮฑ โ ฮฒ โ ฮฒ
Note ฮฑ
and ฮฒ
are introduced before they are used in the type of const
. These considerations motivate the definitions of contexts and their validity (basically, these state when a context is valid: when empty, when an empty context is extended with a new base type, with a new term to type binding, and so on).
Multiple bindings for the same variable (identifier) can occur in the same context, and then the rightmost binding takes precedence.
We write ฮ(z)
to denote the information associated with the identifier z
by context ฮ
.