%%% This is the scribe notes template for CS611
%%% There are several comments preceded by CS611: and boxed in %%%%'s
%%% which indicate where macros should be altered to set up the header
%%% for the paper.  Your Notes should go at the comment SCRIBE NOTES GO HERE!.

%%% In the various .sty files that accompany this .tex file you will
%%% find LaTeX macros that make it easier to typeset inference rules
%%% and programming language constructs.  You must make sure that the
%%% file proof.sty is in a path searched by LaTeX when you try to
%%% use this file.  Take a look to see what macros are available--it
%%% will save you time and make the notes look better.  Feel free to
%%% extend the set of macros--post them to the newsgroup and contact
%%% the course staff if you come up with some good ones so they can be
%%% added to the template.

%%% This template includes examples of how to use some of the macros
%%% to give you an idea of how they work.  (Delete the examples when
%%% you do your scribing.)

\documentclass{article}
\usepackage{611-lecture}
\usepackage{amsmath,amssymb,amsthm,amsfonts}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% CS611: Please fill in these macros as appropriate:
\lecture{23} %% Lecture number
\title{Typed $\lambda$-Calculus}   %% Title of lecture
%\author{Leonid Meyerguz, Stephen Chong, Prakash Linga, Andrew Myers}
%% name of scribe
\date{23 October 2006}    %% Date of lecture
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% See 611.sty for a variety of macros that will be helpful in
% typesetting the lecture
%
% quotes can be used for typewriter font
% <> can be used for angle brackets

\newtheorem{theorem}{Theorem}[section]
\newtheorem{lemma}[theorem]{Lemma}
\newtheorem{proposition}[theorem]{Proposition}
\newtheorem{corollary}[theorem]{Corollary}

\newcommand{\ENV}{\impfnt{Env}}
\newcommand{\FENV}{\impfnt{FEnv}}
\newcommand{\Z}{\mathbb{Z}}
\newcommand{\group}[1]{\left\langle{#1}\right\rangle}

\theoremstyle{definition}
\newtheorem*{defn}{Definition}
\newcommand{\nondet}{\left[\!\kern1pt\right]}
\renewcommand\phi\varphi
\renewcommand\wp[2]{\mathsf{wp}~{#1}~{#2}}
\newcommand\wlp[2]{\mathsf{wlp}~{#1}~{#2}}
\renewcommand\({\begin{eqnarray*}}
\renewcommand\){\end{eqnarray*}}

\newcommand\LOOKUP[2]{\mathrm{LOOKUP}~{#1}~{#2}}
\newcommand\UPDATE[3]{\mathrm{UPDATE}~{#1}~{#2}~{#3}}
\newcommand\MALLOC[2]{\mathrm{MALLOC}~{#1}~{#2}}
\newcommand\EMPTY{\mathrm{EMPTY\mbox{-}STORE}}
\renewcommand\dom[1]{\mathrm{dom}\,{#1}}
\newcommand\p[2]{\langle{#1},\,{#2}\rangle}
\newcommand\bigcdot{\mathrel{\raisebox{1pt}{$\scriptscriptstyle\bullet$}}}
\newcommand\holed[1]{[\,#1\,]}
\newcommand\hole{\holed\bigcdot}
\newcommand\context[1]{E\kern1pt\holed{#1}}
\newcommand\contextHole{\context\bigcdot}
\newcommand\goesto[2]{\underset{#2}{\overset{#1}\longrightarrow}}
\newcommand\ifthenelse[3]{\mathsf{if\ }#1\mathsf{\ then\ }#2\mathsf{\ else\ }#3}
\newcommand\ifpthenelse[3]{\mathsf{ifp\ }#1\mathsf{\ then\ }#2\mathsf{\ else\ }#3}
\newcommand\whiledo[2]{\mathsf{while\ }#1\mathsf{\ do\ }#2}
\newcommand\letin[3]{\mathsf{let\ }#1 = #2\mathsf{\ in\ }#3}
\newcommand\letrec[5]{\mathsf{letrec\ }#1 = #2\mathsf{\ and\ \ldots\ and\ }#3 = #4\mathsf{\ in\ }#5}
\newcommand\letrecone[3]{\mathsf{letrec\ }#1 = #2\mathsf{\ in\ }#3}
\newcommand\true{\ensuremath{\mathsf{true}}}
\newcommand\false{\ensuremath{\mathsf{false}}}
\newcommand\error{\ensuremath{\mathsf{error}}}
\newcommand\pca[3]{\{#1\}\kern1pt{#2}\kern1pt\{#3\}}
\newcommand\states{\Set{St}}
\newcommand\rtc{^{\textstyle *}}
\newcommand\sat\vDash
\newcommand\force\vdash

\newcommand\hyphen{\mbox{-}}
\newcommand\lookup[2]{\nm{LOOKUP}~#1~\mquote{#2}}
\newcommand\update[3]{\nm{UPDATE}~#1~\mquote{#2}~#3}
\newcommand\SBk[1]{\SB{#1}k}
\newcommand\fix[1]{\mathsf{fix}\,{#1}}

\newlength\reasonwidth
\setlength\reasonwidth{3cm}
\newcommand\reasoning[1]{\def\longest{#1}\settowidth{\reasonwidth}{$\displaystyle\longest$}\addtolength{\reasonwidth}{5mm}} %dck 2/12/98
\newcommand\reason[2]{\makebox[\reasonwidth][l]{$\displaystyle{#1}$}\mbox{#2}}

\renewcommand\inj[1]{\mathsf{in}_{#1}}
\newcommand\proj[1]{\pi_{#1}}
\newcommand{\dlt}{\sqsubseteq}
\newcommand\floor[1]{\lfloor{#1}\rfloor}
\newcommand\cf[1]{[\kern1pt{#1}\kern1pt]}
\newcommand\SBpr[1]{\SB{#1}\,\phi\,\rho}%

\newcommand\judge[2]{\force{#1}\ty{#2}}

\begin{document}

\maketitle

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% CS611: SCRIBE NOTES GO HERE!
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\section{Introduction}

_Type checking_ is a lightweight technique for proving
simple properties of programs.  Unlike theorem-proving
techniques based on axiomatic semantics,
type checking usually cannot determine if a program will
produce the correct output.  Instead, it is a way to test
whether a program is _well-formed_, with the idea that a
well-formed program satisfies certain desirable
properties.  The traditional application of type checking
is to show that a program cannot get stuck; that is,
that a type-correct program will
never reach a non-final configuration in its operational
semantics from which its behavior is undefined.  This is a
weak notion of program correctness, but nevertheless very
useful in practice for catching bugs.

Type systems are a powerful technique.  In the past couple
of decades, researchers have discovered how to use type systems
for a variety of different verification tasks.

\section{$\lambda^\to$}

We have already seen some typed languages in class this semester.
For example, ML and the metalanguage used in class for denotational
semantics are both typed.

To explore the idea of type checking itself, we introduce
$\lambda^\to$, a typed variant of the $\lambda$-calculus in which
we assign types to certain $\lambda$-terms according to some typing rules.
A $\lambda$-term is considered to be well-formed if a type can
be derived for it using the rules.  We will give operational and denotational
semantics for this language.  Along the way, we will discover
some interesting properties that give insight about typing in more
complex languages.

\section{Syntax}

The syntax of $\lambda^\to$ is similar to that of untyped $\lambda$-calculus, with some notable differences.  There are two kinds of inductively-defined expressions, _terms_ and _types_:
\[
\begin{array}{lrcl}
\mbox{terms} & e &::=& n \bnf "true" \bnf "false" \bnf "null" \bnf x \bnf e_1\,e_2 \bnf \lam{x\ty\tau}e\\
\mbox{types} & \tau &::=& "int" \bnf "bool" \bnf "unit" \bnf \tau _1 \rightarrow \tau _2
\end{array}
\]
One difference is that the natural numbers, Boolean constants, and "null" are taken to be primitive symbols and not defined as $\lambda$-terms.  Another difference is that a $\lambda$-abstraction explicitly mentions the type of its argument.

A _value_ is either a number, a Boolean constant, "null", or a closed abstraction $\lam{x\ty\tau}e$. The set of values is denoted \Set{Val}.  The set of types is denoted \Set{Type}.

There is a set of _typing rules_, given below, that can be used to associate a type
with a term.  If a type $\tau$ can be derived for a term $e$ according to the typing
rules, we write $\judge e\tau$.  This metaexpression is called a _type judgement_.

For example, every number has type "int", thus $\judge 3{"int"}$.
The type "unit" is the type of the value "null", and nothing else
has this type.  The function $\nm{TRUE}\sub{int} =
\lam{x\ty "int"}{\lam{y\ty"int"}x}$ has the type $"int"
\rightarrow ("int" \rightarrow "int")$.  The $\rightarrow$
constructor associates to the right, so
$"int" \rightarrow ("int" \rightarrow "int")$
is the same as
$"int" \rightarrow "int" \rightarrow "int"$.  Thus we can write
\begin{eqnarray*}
\nm{TRUE}\sub{int} &\definedas& (\lam{x\ty "int"}{\lam{y\ty"int"}x}) : "int" \rightarrow "int" \rightarrow "int".
\end{eqnarray*}
Not all $\lambda$-terms can be typed, for instance $\lam{x\ty"int"}{xx}$ or $"true"~3$.  These expressions are considered nonsensical.

Right now, we cannot do anything interesting with integers or Booleans, because we do not have any operations on them.  Later on we will be adding other typed constants such as $"plus":"int"\to"int"\to"int"$ and $"equal":"int"\to"int"\to"bool"$, but for now they are just there to set the stage.

\section{Small-Step Operational Semantics and Type Correctness}

The small-step CBV operational semantics of $\lambda^\to$ is the same as that of the untyped $\lambda$-calculus.  The presence of types does not alter the evaluation rules for expressions. 
\(
E\ \ ::=\ \ E~e \bnf v~E \bnf \hole &\quad& (\lam{x\ty\tau}e)~v\ \ \to\ \ \subst evx
\)

We will eventually show that these reduction rules preserve well-formedness
in the sense that if $e$ has type $\tau$ and $e\stackrel*\rightarrow e'$,
then $e'$ also has type $\tau$.  Coupled with the observation that all well-typed
terms are either values or can be further reduced, this says that
no well-typed term can become stuck.  Thus the typing rules can be used
in place of run-time type checking to ensure strong typing.

It is natural to ask what a type-incorrect term
might look like and how it could get stuck.
Recall our function definition for
$\nm{TRUE}\sub{int}$ above, and consider the following additional
definition:
\begin{eqnarray*}
\nm{IF}\sub{int} &\definedas& \lam{t\ty "int" \rightarrow "int" \rightarrow
"int"}{\lam{a\ty"int"}{\lam{b\ty"int"}{t~a~b}}}.
\end{eqnarray*}
Clearly, $\nm{IF}\sub{int}~\nm{TRUE}\sub{int}~2~3$ evaluates to 2.
However, $\nm{IF}\sub{int}~"true"~2~3\rightarrow "true"~2~3$, and this
expression is meaningless, since "true" is not a function and cannot
be applied to anything.  Therefore, the program would be stuck at this point.

\section{Typing Rules}

\newcommand\Gjudge[2]{\Gamma\judge{#1}{#2}}%
The typing rules will determine which terms are well-formed $\lambda^\to$ programs.
They are a set of rules that allow the derivation of _type judgements_ of the form $\Gjudge e\tau$.
Here $\Gamma$ is a _type environment_, a partial map from variables to types used to determine the types of the free variables in $e$.  The domain of $\Gamma$ as a partial function $\Set{Var}\rightharpoonup\Set{Type}$ is
denoted $\dom\Gamma$.

The environment $\Gamma[\tau/x]$ is obtained by rebinding $x$ to $\tau$ (or creating the binding anew if $x\not\in\dom\Gamma$):
\(
\Gamma[\tau/x](y) &\definedas&
\begin{cases}
\Gamma(y), & \mbox{if $y\neq x$ and $y\in\dom\Gamma$,}\\
\tau, & \mbox{if $y=x$,}\\
\mbox{undefined,} & \mbox{otherwise.}
\end{cases}
\)
The notation $\Gamma,\,x\ty\tau$ is synonymous with $\Gamma[\tau/x]$.  The former is standard notation in the literature.  Also, one often sees $x\ty\tau\in\Gamma$, which means just $\Gamma(x)=\tau$.

We also write $\Gamma\judge e\tau$ as a metaexpression to mean that the type judgement $\Gamma\judge e\tau$ is derivable from the typing rules.  The environment $\varnothing$ is the empty environment, and the judgement $\judge e\tau$ is short for $\varnothing \judge e\tau$.

The typing rules are:
\[
\begin{array}{c@{\hspace{1cm}}c@{\hspace{1cm}}c@{\hspace{1cm}}c@{\hspace{1cm}}c}
\Gjudge n{"int"} & \Gjudge{"true"}{"bool"} & \Gjudge{"false"}{"bool"} & \Gjudge{"null"}{"unit"} & \Gamma,\,x\ty\tau \judge x\tau
\end{array}
\]
\begin{center}
\begin{tabular}{c@{\hspace{1cm}}c}
\infer{\Gjudge{e_0\,e_1}{\tau}}{\Gjudge{e_0}{\sigma\rightarrow\tau} & \Gjudge{e_1}\sigma}
& \infer{\Gjudge{(\lam{x\ty\sigma}e)}{\sigma\to\tau}}{\Gamma,\,x\ty\sigma \judge e{\tau}}
\end{tabular}
\end{center}
Let us explain these rules in more detail.
\begin{itemize}
\item
The first four rules just say that all the base values have their corresponding base types.
\item
For a variable $x$, $\Gjudge x\tau$ holds if the binding $x\ty\tau$ appears in the type environment $\Gamma$; that is, if $\Gamma(x)=\tau$.
\item
An application expression $e_0\,e_1$ represents the result of applying the function represented by $e_0$ to the argument represented by $e_1$.  For this to have type $\tau$, $e_0$ must be a function of type $\sigma\to\tau$ for some $\sigma$, and its argument $e_1$ must have type $\sigma$.  This is captured in the typing rule for $e_0\,e_1$.
\item
Finally, a $\lambda$-abstraction $\lam{x\ty\sigma}e$ is supposed to represent a function.  The type of the input should match the annotation in the term, thus the type of the function must be $\sigma\to\tau$ for some $\tau$.  The type $\tau$ of the result is the type of the body under the extra type assumption $x\ty\sigma$.  This idea is captured in the typing rule for $\lambda$-abstractions.
\end{itemize}

Every well-typed $\lambda^\to$ term has a proof tree consisting of applications of the typing rules to derive a type for the term.  We can type-check a term by constructing this proof tree.  For example, consider the program $(\lam{x\ty"int"}{\lam{y\ty"bool"}x})~2~"true"$, which evaluates to 2.  Since $\judge 2{"int"}$, we expect $\judge {((\lam{x\ty"int"}{\lam{y\ty"bool"}x})~2~"true")}{"int"}$ as well.  Here is a proof of that fact:
\begin{center}
\begin{tabular}{c}
\infer{\judge{((\lam{x\ty"int"}{\lam{y\ty"bool"}x})~2~"true")}{"int"}}
      {\infer{\judge{((\lam{x\ty"int"}{\lam{y\ty"bool"}x})~2)}{"bool"\to"int"}}
             {\infer{\judge{(\lam{x\ty"int"}{\lam{y\ty"bool"}x})}{"int"\to"bool"\to"int"}}
                    {\infer{x\ty"int"\judge{(\lam{y\ty"bool"}x)}{"bool"\to"int"}}
                           {x\ty"int",\,y\ty"bool"\judge{x}{"int"}}}
           & {\judge 2{"int"}}}
    & {\judge{"true"}{"bool"}}}
\end{tabular}
\end{center}

An automated type checker can effectively construct proof trees like this in order to test whether a program is type-correct.

Note that types, if they exist, are unique.  That is, if $\Gjudge e\tau$ and $\Gjudge e{\tau'}$, then $\tau=\tau'$.  This can be proved easily by structural induction on $e$, using the fact that there is exactly one typing rule that applies in each case, depending on the form of $e$.

\section{Expressive Power}

By now you may be wondering if we have lost any of the expressive power
of $\lambda$-calculus by introducing types.  The answer to this
question is a resounding _yes_.  For example, we can no longer compose
arbitrary functions, since they may have mismatched types.

More importantly, we have lost the ability to write loops.  Recall the paradoxical combinator
\begin{eqnarray*}
\Omega &\definedas& (\lam x{xx})~(\lam x{xx}).
\end{eqnarray*}
Let us show that any attempt to derive a typing for the term $\lam{x\ty\sigma}{xx}$ must fail:
\begin{center}
\begin{tabular}{c}
\infer{\Gjudge{(\lam{x\ty\sigma}{xx})}{\sigma\rightarrow\tau}} {
    \infer {\Gamma,\,x\ty\sigma \judge{xx}\tau } {
        \Gamma,\,x\ty\sigma \judge x{\sigma\rightarrow\tau} &
        \Gamma,\,x\ty\sigma \judge x\sigma
    }
}
\end{tabular}
\end{center}
We see that we must have both $\Gamma,\,x\ty\sigma\judge x{\sigma\rightarrow\tau}$ and
$\Gamma,\,x\ty\sigma\judge x\sigma$.  However, since types are unique, this is impossible; we cannot
have $\sigma=\sigma\to\tau$, since no type expression can be a subexpression
of itself.  We conclude that the term $\lam{x\ty\sigma}{xx}$ cannot be typed.

In fact, we will see later
that we cannot write down _any_ nonterminating program in $\lambda^\to$.
This will turn out be true from an operational perspective as well.
In later lectures we will show how to extend the type
system to allow loops and nonterminating programs.

\section{Denotational Semantics}

Before we can give the denotational semantics for $\lambda^\to$,
we need to define a new meaning function $\Te\cdot$ that maps each
type to a domain associated with that type.  For this type system,
the definition of $\Te\cdot$ is straightforward:
\begin{eqnarray*}
\Te{"int"} &\definedas& {\mathbb Z}\\
\Te{"bool"} &\definedas& \{"true", "false"\}\\
\Te{"unit"} &\definedas& \{"null"\}\\
\Te{\sigma\rightarrow\tau} &\definedas& \Te{\sigma}\rightarrow\Te{\tau}.
\end{eqnarray*}
In the last equation, note that the $\to$ on the left-hand side is just a symbol
in the language of types, a syntactic object, whereas the $\to$ on the
right-hand side is a semantic object, namely the operator that constructs
the space of functions between a given domain and range.
For now, these domains need not have any ordering properties; they are just
sets. So we have $\Tr T\cdot:\Set{Type}\to\Set{Set}$.

For any closed term $e$, if $\judge e\tau$, then we expect the denotation of $e$ to be an
element of $\Te\tau$.  More generally, for a term $e$ possibly containing free variables,
if there is a type environment $\Gamma$ and a value environment
$\rho$ such that $\rho$ and $\Gamma$ are defined on all the free variables
of $e$ and $\rho(x)\in\Te{\Gamma(x)}$
for all $x\in\FV e$, and if $\Gjudge e\tau$, then we expect the denotation of $e$ in environment
$\rho$ to be an element of $\Te\tau$.

We say that the value environment $\rho$ _satisfies_ a type
environment $\Gamma$ and write $\rho\sat\Gamma$ if
$\dom\Gamma\subseteq\dom\rho$ and for every $x\in\dom\Gamma$,
$\rho(x)\in\Te{\Gamma(x)}$.

We only define the meaning function for well-typed
expressions.  This kind of semantics---where we do not assign any meaning
to ill-formed terms---is known as a _Church-style semantics_.
The alternative is _Curry-style
semantics_, in which we give a meaning even to programs that are
not well-typed. Our operational semantics, for example,
talks about how to evaluate even ill-typed terms.

We are now ready to give the denotational semantics
for typed $\lambda$-terms.  The following function is
defined only for $e$, $\Gamma$, and $\rho$ such that
$\rho\sat\Gamma$ and $e$ is well-typed under $\Gamma$;
that is, $\Gjudge e\tau$ for some type $\tau$.
\renewcommand\C[3]{\Tr C{#1}\kern1pt{#2}\kern1pt{#3}}
\renewcommand\Cr[1]{\C{#1}\Gamma\rho}
\(
\Cr{n} &\definedas& n\\
\Cr{"true"} &\definedas& "true"\\
\Cr{"false"} &\definedas& "false"\\
\Cr{"null"} &\definedas& "null"\\
\Cr{x} &\definedas& \rho(x),\quad x\in\dom\Gamma\\
\Cr{e_0\,e_1} &\definedas& (\Cr{e_0})~(\Cr{e_1})\\
\Cr{\lam{x\ty\tau}e} &\definedas& \lm v{\Te{\tau}}{\C{e}{\Gamma[\tau/x]}{\rho[v/x]}}
\)

\section{Soundness}

It is possible to show that $\Cr\cdot$ satisfies
the following soundness condition: for all $\rho$, $\Gamma$, $e$, and $\tau$,
\begin{eqnarray*}
\rho\sat\Gamma\ \wedge\ \Gjudge e\tau &\Rightarrow& \Cr{e} \in \Tr T{\tau}.
\end{eqnarray*}

The proof is by induction on the structure of $e$.
The only interesting step is the case of a $\lambda$-term, which requires the observation
\(
\rho\sat\Gamma\ \wedge\ v\in\Tr T\tau
&\Rightarrow& \rho[v/x] \sat \Gamma[\tau/x].
\)

Note that $\bot$ does not appear anywhere in this
semantics. We didn't need it because we never took a fixpoint.
We can conclude that all typed $\lambda$-calculus programs terminate,
because they represent total functions.

Of course, we will also want to see that the operational semantics
are adequate with respect to this model to ensure that our evaluation
relation actually produces the values of the correct type that
the denotational model advertises are there.
For example, for a closed term $e$ such that $\judge e{"int"}$, 
the adequacy condition would say that
\(
e \stackrel*\to n &\Leftrightarrow& \C{e}\varnothing\varnothing = n.
\)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\end{document}
