-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlec2.tex
276 lines (260 loc) · 16.7 KB
/
lec2.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
\section*{Lecture 2, Type Safety}
The goal of this lecture was to proof type safety for STLC using logical relations. First we need to consider what type safety is. The classical mantra for type safety is ``Well-typed programs do not \emph{go wrong}.'' It depends on the language and type system what \emph{go wrong} means, but in our case a program has \emph{gone wrong} if it is stuck\footnote{If we consider language-based security for information flow control the notion of \emph{go wrong} would be that there is an undesired flow of information} (an expression is stuck if it is irreducible but not a value).
\subsection*{Type Safety for STLC}
\begin{stlctypesafety}[Type Safety for STLC]
If $\mtenv \vdash e : \tau$ and $e \evaltos e'$ then $\val(e')$ or $\exists e''. \; e' \evalto e''$.
\end{stlctypesafety}
Traditionally type safety is proven by two lemmas: progress and preservation.
\begin{progress}[Progress]
If $\mtenv \vdash e : \tau$ then $\val(e)$ or $\exists e'. \; e \evalto e'$.
\end{progress}
Progress is normally proved by induction on the typing derivation.
\begin{preservation}[Preservation]
If $\mtenv \vdash e : \tau$ and $e \evalto e'$ then $\mtenv \vdash e' : \tau$.
\end{preservation}
Preservation is normally proved by induction on the evaluation relation.
Preservation is also known as \emph{subject reduction}. Progress and
preservation talk about one step, so to prove type safety we have to
do induction on the evaluation relation. Here we do not want to prove type safety the traditional way. We want to prove it using a logical predicate. We use a logical predicate rather than a logical relation because type safety is a unary property.
The notation will here be changed compared to the one from lecture 1. We define the logical predicate in two parts: a value interpretation and an expression interpretation. The value interpretation is a function from types to the power set of closed values:
\[
\vpred{ - } : \tarrow{type}{\curly{P}(ClosedVal)}
\]
The value interpretation is defined as:
\begin{align*}
\vpred{bool} & = \{ \true, \false \}\\
\vpred{\tarrow{\tau_1}{\tau_2}} & = \{\tlabs{x}{\tau_1}{e} \vbar \forall v \in \curly{V}\sem{\tau_1}.\; e [v/x] \in \curly{E}\sem{\tau_2}\}
\end{align*}
We define the expression interpretation as:
\[
\epred{\tau} = \{e \vbar \forall e'. \; e \evaltos e' \pand \irred(e') \implies e' \in \curly{V}\sem{\tau} \}
\]
Notice that neither \vpred{\tau} nor \epred{\tau} requires
well-typedness. Normally this would be a part of the predicate, but as
the goal is to prove type safety we do not want it as a part of the
predicate. In fact, if we did include a well-typedness requirement,
then we would end up having to prove preservation for some of the
proofs to go through. We do, however, require the value interpretation
to only contain closed values.
The predicate $\irred$ is defined as:
\[
\irred(e) \eqdef \not\exists e'. \; e \evalto e'
\]
%TODO: Exlpain in words what irred is.
The sets are defined on the structure of the types. \vpred{\tarrow{\tau_1}{\tau_2}} contains \epred{\tau_2}, but \epred{\tau_2} uses $\tau_2$ directly in \vpred{\tau_2}, so the definition is structurally well-founded. To prove type safety we first define a new predicate, $\safe$:
\[
\safe(e) \eqdef \forall e' . \; e \evaltos e' \implies \val(e') \vee \exists e
''. \; e' \evaltos e''
\]
%TODO: Explain in words what safe is
We are now ready to prove type safety. Just like we did for strong normalization, we prove type safety in two steps:
\[
\circled{a} \quad \mtenv \vdash e : \tau \implies e \in \epred{\tau}
\]
\[
\circled{b} \quad e \in \epred{\tau} \implies \safe(e)
\]
Rather than proving \circled{a} directly we prove a more general theorem and get \circled{a} as a corollary. But we are not yet in a position to state the theorem. First we need to define define the interpretation of environments:
\begin{align*}
\gpred{\mtenv} & = \{ \emptyset \} \\
\gpred{\Gamma,x:\tau} & = \{\gamma[x \mapsto v] \vbar
\gamma \in \gpred{\Gamma} \pand
v \in \vpred{\tau}\}
\end{align*}
Further we need to define semantic type safety:
\[
\Gamma \models e : \tau \eqdef \forall \gamma \in \gpred{\Gamma} . \; \gamma(e) \in \epred{\tau}
\]
We can now define our generalized version of \circled{a}.
\begin{btypesafety}[Fundamental Property]
If $\Gamma \vdash e : \tau$ then $\Gamma \models e : \tau$
\end{btypesafety}
A theorem like this would typically be the first you prove after defining a logical relation. The theorem says that every syntactic type safety implies semantic type safety.
We also alter the \circled{b} part of the proof, so we prove
\[
\mtenv \models e : \tau \implies \safe(e)
\]
\begin{proof}[Proof. (Altered \circled{b})]
Suppose $e \evaltos e'$ for some $e'$, then we need to show $\val(e')$ or $\exists e''. \; e' \evalto e''$. We proceed by casing on whether or not $\irred(e')$:
\case{$\neg \irred(e')$} this case follows directly from the definition of $\irred$. $\irred(e')$ is defined as $\not \exists e''. \; e' \evalto e''$ and as the assumption is $\neg \irred(e')$ we get $\exists e''. \; e' \evalto e''$.
\case{$\irred(e')$} By assumption we have $\mtenv \models e : \tau$. As the typing context is empty we choose the empty substitution and get $e \in \epred{\tau}$. We now use the definition of $e \in \epred{\tau}$ with what we supposed, $e \evaltos e'$, and the case assumption, $\irred(e')$, to conclude $e' \in \vpred{\tau}$. As $e'$ is in the value interpretation of $\tau$ we can conclude $\val(e')$.
\end{proof}
To prove the Fundamental Property we need a substitution lemma:
\begin{lemma}[Substitution]
Let $e$ be syntactically well-formed term, let $v$ be a closed value and let $\gamma$ be a substitution that map term variables to closed values, and let $x$ be a variable not in the domain of $\gamma$, then
\[
\extsub{\gamma}{x}{v}(e) = \subst{\gamma(e)}{x}{v}
\]
\end{lemma}
\begin{proof}
By induction on the size of $\gamma$.
\case{$\gamma = \emptyset$} This case is immediate by how substitution is defined. That is by definition we have $[x \mapsto v] e = \subst{e}{v}{x}$.
\case{$\gamma = \gamma'[y \mapsto v']$, $x\neq y$} In this case our induction hypothesis is:
\[
\gamma'[x \mapsto v] e = \subst{\gamma'(e)}{v}{x}
\]
We wish to show
\[
\gamma'[y \mapsto v'][x \mapsto v] e = \subst{\gamma'[y \mapsto v'](e)}{v}{x}
\]
\begin{align}
\gamma'[y \mapsto v'][x \mapsto v] e & = \gamma'[x \mapsto v][y \mapsto v'] e \label{sub:step1}\\
& = \gamma'[x \mapsto v] (\subst{e}{v'}{y}) \label{sub:step2}\\
& = \subst{\gamma'(\subst{e}{v'}{y})}{x}{v}\label{sub:step3}\\
& = \subst{\gamma'[y \mapsto v'](e)}{x}{v}\label{sub:step4}
\end{align}
In the first step (\ref{sub:step1}) we swap the two mappings. It is safe to do so as both $v$ and $v'$ are closed so we know that no variable capturing will occur. In the second step (\ref{sub:step2}) we just use the definition of substitution (as specified in the first lecture note). In third step (\ref{sub:step3}) we use the induction hypothesis\footnote{The induction hypothesis actually has a number of premises, as an exercise convince yourself that they are satisfied.}. Finally in the last step (\ref{sub:step4}) we use the definition of substitution to get the $y$ binding out as an extension of $\gamma'$.
\end{proof}
\begin{proof}[Proof. (Fundamental Property)] Proof by induction on the typing judgment.
\case{\TAbs} \\
We need to show $\Gamma \models \tlabs{x}{\tau_1}{e} : \tarrow{\tau_1}{\tau_2}$. First suppose $\gamma \in \gpred{\Gamma}$. Then we need to to show
\[
\gamma(\tlabs{x}{\tau_1}{e}) \in \epred{\tarrow{\tau_1}{\tau_2}} \equiv
(\tlabs{x}{\tau_1}{\gamma(e)}) \in \epred{\tarrow{\tau_1}{\tau_2}}
\]
Now suppose that $\tlabs{x}{\tau_1}{\gamma(e)} \evaltos e'$ and $\irred(e')$. We then need to show $e' \in \vpred{\tarrow{\tau_1}{\tau_2}}$. Since $\tlabs{x}{\tau_1}{\gamma(e)}$ is a value it is irreducible, and we can conclude it took no steps. In other words $e' = \tlabs{x}{\tau_1}{\gamma(e)}$. So we need to show $\tlabs{x}{\tau_1}{\gamma(e)} \in \vpred{\tarrow{\tau_1}{\tau_2}}$. Now suppose $v \in \vpred{\tau_1}$ then we need to show $\gamma(e)[v/x] \in \epred{\tau_2}$.
Keep the above proof goal in mind and consider the induction hypothesis:
\[
\Gamma, x: \tau_1 \models e : \tau_2
\]
Instantiate this with $\gamma[x \mapsto v]$. We have $\gamma[x \mapsto v] \in \gpred{\Gamma, x : \tau_1}$ because we started by supposing $\gamma \in \gpred{\Gamma}$ and we also had $v \in \vpred{\tau_2}$. The instantiation gives us $\gamma[x \mapsto v] (e) \in \epred{\tau_2} \equiv \gamma(e)[v/x] \in \epred{\tau_2}$. The equivalence is justified by the substitution lemma we proved. Now recall our proof goal, we now have the result we wanted to show.
\case{\TApp} show this case as an exercise.\\
The remaining cases were not proved during the lecture.
\end{proof}
Now consider what happens if we add pairs to the language.
%TODO: Clarify what additions to STLC are needed for pairs.
\begin{comment}
\begin{align*}
&\fst <v_1,v_2> \evalto v_1 \\
&\snd <v_1,v_2> \evalto v_2
\end{align*}
\end{comment}
We need to add a clause to the value interpretation:
\[
\vpred{\tau_1 \times \tau_2} = \{<v_1,v_2> \vbar v_1 \in \vpred{\tau_1} \pand v_2 \in \vpred{\tau_2}\}
\]
There is nothing surprising in this addition to the value relation, and it should not be a challenge to show the pair case of the proofs.
%omitted: '3rd part of LR recipe is mostly about functions - Contravariance problem.'
If we extend our language with sum types. %that is
\[
e::= \dots \vbar \inl \; v \vbar \inr \; v \vbar \scase \; e \caseof \; \inl \; x => e_1 \quad \inr \; x => e_2
\]
Then we need to add the following clause to the value interpretation:
\[
\vpred{\tau_1 + \tau_2} = \{\inl \; v \vbar v \in \vpred{\tau_1}\} \cup
\{\inr \; v \vbar v \in \vpred{\tau_2}\}
\]
It turns out this clause is sufficient. One might think that is is necessary to require the body of the match to be in the expression interpretation, which looks something like $\forall e_1 \in \epred{\tau}$. This requirement will, however, give well-foundedness problems, as $\tau$ is not a structurally smaller type than $\tau_1 + \tau_2$. It may come as a surprise that we do not need to relate the expressions as the slogan for logical relations is ``Related inputs to related outputs.''
\subsubsection*{Recursive Types}
In this subsection we will motivate and introduce recursive types. This will set the scene for lecture 3.
First consider the following program in the \emph{untyped} lambda calculus:
\[
\Omega = (\labs{x}{x \; x}) \; (\labs{x}{x \; x})
\]
The interested reader can now try to evaluate the above expression. After a $\beta$-reduction and a substitution we end up with $\Omega$ again, so the evaluation of this expression diverges. Moreover, it is not possible to assign a type to $\Omega$ (again the interested reader may try to verify this by attempting to assign a type). It can hardly come as a surprise that it cannot be assigned a type, as we previously proved that the simply typed lambda calculus is strongly normalizing so if we could assign $\Omega$ a type, then it would not diverge.
To type $\Omega$ we need recursive types. If we are able to type $\Omega$, then we do not have strong normalization (as $\Omega$ is not strongly normalizing). With recursive types we can type structures that are inherently inductive such as lists, trees, and streams. In an ML like language a declaration of a tree type would look like this:
\begin{lstlisting}
type tree = Leaf
| Node of int * tree * tree
\end{lstlisting}
In Java we could define a tree class with an int field and fields for the sub trees:
\begin{lstlisting}
class Tree {
int value;
Tree left, right;
}
\end{lstlisting}
So we can define trees in our programming languages, but we cannot define them in the lambda calculus. Let us try to find a reasonable definition for recursive types by considering what properties are needed to define trees. We want a type that can either be a node or a leaf. A leaf can be represented by unit (as it here does not carry any information), and a node is the product of an int and two nodes. We put the two together with the sum type, as it is:
\[
tree = 1 + (int * tree * tree)
\]
This is what we want, but we cannot specify this. We try to define $tree$, but $tree$ appears on the right hand side, which is self-referential. Instead of writing $tree$ we use a type variable $\alpha$:
\begin{align*}
\alpha &= 1 + (int \times \alpha \times \alpha) \\
&= 1 + (int \times (int \times \alpha \times \alpha) \times (int \times \alpha \times \alpha)) \\
&\vdots
\end{align*}
All the sides of the above equations are equal, and they are all trees. We could keep going and get an infinite system of equations. If we keep substituting the definition of $\alpha$ for $\alpha$ we keep getting bigger and bigger types. All of the types are trees, and all of them are finite. If we take the limit of this process, then we end up with an infinite tree, and that tree is the tree we conceptually have in our minds. So what we need is the fixed point of the above equation.
Let us define a recursive function who's fixed point we want to find:
\[
F = \lambda \alpha :: type. 1 + (int \times \alpha \times \alpha)
\]
We want the fixed point which by definition is $t$ such that
\[
t = F(t)
\]
So we want
\[
tree = F(tree)
\]
The fixed point of this function is written:
\[
\mu \alpha.\; F(\alpha)
\]
Here $\mu$ is a fixed point type constructor. As the above is the fixed point, then by definition it should be equal to $F$ applied to it:
\[
\mu \alpha.\; F(\alpha) = F(\mu \alpha.\; F(\alpha))
\]
Now let us make this look a bit more like types by substituting $F(\alpha)$ for $\tau$.
\[
\mu \alpha.\; \tau = F(\mu \alpha.\; \tau)
\]
The right hand side is really just $\tau$ with $\mu \alpha. \; \tau$ substituted with $\tau$:
\[
\mu \alpha.\; \tau = \tau[\mu \alpha. \; \tau / \alpha]
\]
We are going to introduce the recursive type $\mu \alpha.\; \tau$ to our language. When we have a recursive type we can shift our view to an expanded version $\tau[\mu \alpha. \; \tau / \alpha]$ and contract back to the original type. Expanding the type is called $\unfold$ and contracting is is called $\fold$.
\[
\begin{tikzpicture}[->,>=stealth',shorten >=1pt,auto,node distance=3cm,
thick,main node/.style={rectangle}]
\node[main node] (1) {$\mu\alpha.\; \tau$};
\node[main node] (2) [right of=1] {$\tau[\mu \alpha. \; \tau / \alpha]$};
\path[every node/.style={font=\sffamily\small}]
(1) edge [bend left] node [above] {$\unfold$} (2)
(2) edge [bend left] node [below] {$\fold$} (1);
\end{tikzpicture}
\]
With recursive types in hand we can now define our tree type:
\[
tree \eqdef \mu \alpha. \; 1 + (int \times \alpha \times \alpha)
\]
When we want to work with this, we would like to be able to get under the $\mu$. Say we have $e : tree$ that is an expression $e$ with type $tree$, then we want to be able to say whether it is a leaf or a node. To do so we unfold the type to get the type where $\alpha$ has been substituted with the definition of $tree$ and the outer $\mu\alpha.$ has been removed. With the outer $\mu\alpha.$ gone we can match on the sum type to find out whether it is a leaf or a node. When we are done working with the type we can fold it back to the original tree type.
\[
\begin{tikzpicture}[->,>=stealth',shorten >=1pt,auto,node distance=3cm,
thick,main node/.style={rectangle}]
\node[main node] (1) {$tree=\mu\alpha.\; 1+(int \times \alpha \times \alpha)$};
\node[main node] (2) [right of=1,xshift=5cm] {$1+(int \times (\mu\alpha.\; 1+(int \times \alpha \times \alpha)) \times (\mu\alpha.\; 1+(int \times \alpha \times \alpha)))$};
\path[every node/.style={font=\sffamily\small}]
(1) edge [bend left=10] node [above] {$\unfold$} (2)
(2) edge [bend left=10] node [below] {$\fold$} (1);
\end{tikzpicture}
\]
This kind of recursive types is called iso-recursive types, because there is an isomorphism between a $\mu\alpha. \; \tau$ and its unfolding $\tau[\mu\alpha.\; \tau / \alpha]$.
STLC extended with recursive types is defined as follows:
\begin{align*}
\tau &::= \dots \vbar \mu \alpha. \; \tau \\
e &::= \dots \vbar \fold \; e \vbar \unfold \; e \\
v &::= \dots \vbar \fold \; v\\
E &::= \dots \vbar \fold \; E \vbar \; \unfold \; E
\end{align*}
\[
\unfold \; (\fold \; v) \evalto v
\]
\[
\TFold \hspace{2cm} \TUnfold
\]
With this we could define the type of an integer list as:
\[
int\; list \eqdef \mu\alpha.\; 1 + (int \times \alpha)
\]
%TODO: Typing omega
\begin{comment}
\[
\Omega = (\tlabs{x}{\mu\alpha.\; \tarrow{\alpha}{\tau}}{(\unfold \; x) \; x})
\]
\end{comment}
\subsection*{Exercises}
\begin{enumerate}
\item Prove the TApp case of the Fundamental Property
\end{enumerate}
\clearpage