summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--transp-inf110-02-typage.tex180
1 files changed, 135 insertions, 45 deletions
diff --git a/transp-inf110-02-typage.tex b/transp-inf110-02-typage.tex
index 3d44a81..380d40d 100644
--- a/transp-inf110-02-typage.tex
+++ b/transp-inf110-02-typage.tex
@@ -3583,7 +3583,7 @@ callcc\_cps (fun kf -> fun k -> kf 42 (fun v -> sum\_cps v 1 k)) (fun x -> x) ;;
\end{frame}
%
\begin{frame}
-\frametitle{Continuation Passing Style : transformation des types}
+\frametitle{Continuation Passing Style : systématisation}
\textcolor{blue}{Définissons la transformation CPS de façon
systématique.}
@@ -3593,11 +3593,85 @@ callcc\_cps (fun kf -> fun k -> kf 42 (fun v -> sum\_cps v 1 k)) (fun x -> x) ;;
{\footnotesize Prenons ici les notations logiques pour les types :
notamment, $\Rightarrow$ désigne le type fonction.\par}
+\medskip
+
+\itempoint Fixons un type $Z$ de « retour ultime ». On pose
+\alert{$\mathop{\sim}P := (P\Rightarrow Z)$} pour le type d'« une
+continuation qui attend une valeur de type $P$ » et
+$\mathop{\sim}\mathop{\sim}P$ pour « une valeur $P$ passée par
+continuation ».
+
+\medskip
+
+\itempoint Noter que $x:P \;\vdash\; \lambda(k:\mathop{\sim}P).kx :
+\mathop{\sim}\mathop{\sim}P$ (transformation d'une valeur « directe »
+en valeur passée par continuation).
+
+\medskip
+
+{\footnotesize On si on préfère voir ça comme une fonction :
+ $\lambda(x:P).\,\lambda(k:\mathop{\sim}P).\,kx$ a pour type $P
+ \Rightarrow \mathop{\sim}\mathop{\sim}P$.\par}
+
+\medskip
+
+\itempoint On va passer \alert{toutes} les valeurs par continuation :
+tous les types transformés prendront la forme
+$\mathop{\sim}\mathop{\sim}T$.
+
\smallskip
-\itempoint Fixons un type $Z$ de « retour ultime ». On définit une
-transformation $P \mapsto P^\diamond$ des types (=propositions) en posant
-$\mathop{\sim}P := (P\Rightarrow Z)$, puis (inductivement) :
+Mais en plus de ça, les fonctions renvoient leur valeur par
+continuation : une fonction de type $P \Rightarrow Q$ va devenir $P
+\Rightarrow \mathop{\sim}Q \Rightarrow Z$, c'est-à-dire $P \Rightarrow
+\mathop{\sim}\mathop{\sim}Q$, et sera elle-même passée par
+continuation, donc $\mathop{\sim}\mathop{\sim}(P \Rightarrow
+\mathop{\sim}\mathop{\sim}Q)$ {\footnotesize (sans compter que $P$ et
+ $Q$ peuvent eux-mêmes changer)}.
+
+\end{frame}
+%
+\begin{frame}
+\frametitle{Continuation Passing Style : l'essence de la transformation}
+
+\itempoint Définissons la transformation CPS d'abord dans le
+$\lambda$-calcul \alert{non typé} : par induction sur la complexité du
+terme :
+\begin{itemize}
+\item $v^{\cps} = \lambda k.kv$ si $v$ est une variable (c'est la
+ transformation de $P$ en $\mathop{\sim}\mathop{\sim}P$ définie
+ ci-dessus).
+\item $(\lambda v.t)^{\cps} = \lambda k.\, k(\lambda v.\, t^{\cps})$
+ (idem pour une fonction, dont le corps est CPS-ifié).
+\item pour l'application : \[(fx)^{\cps} = \lambda
+ k.\,f^{\cps}(\lambda f_0.\, x^{\cps}(\lambda x_0.\, f_0 x_0 k))\] ce
+ code se comprend ainsi : on invoque $f^{\cps}$ pour recevoir sa
+ valeur « directe » $f_0$ (qui est quand même une fonction dans le
+ style CPS), puis $x^{\cps}$ pour recevoir sa valeur « directe »
+ $x_0$, puis on appelle la fonction $f_0$ avec la valeur $x_0$ et la
+ continuation $k$ de l'ensemble de l'expression,
+\item $\texttt{callcc}^{\cps} = \lambda \ell.\, \ell(\lambda g.\,
+ \lambda k.\, g(\lambda v.\, \lambda k_0.\, kv)\,k)$
+\end{itemize}
+
+\medskip
+
+\itempoint Ce code \alert{porte les graines d'un interpréteur}
+(eval/apply) du $\lambda$-calcul dans le $\lambda$-calcul : il impose
+d'ailleurs l'évaluation en appel-par-valeurs.
+
+\end{frame}
+%
+\begin{frame}
+\frametitle{Continuation Passing Style : transformation des types}
+
+{\footnotesize Il reste à typer tout ça !\par}
+
+\smallskip
+
+\itempoint Rappelons qu'on a fixé $Z$ et posé $\mathop{\sim}P :=
+(P\Rightarrow Z)$. On définit une transformation $P \mapsto
+P^\diamond$ des types (=propositions) par (inductivement) :
\begin{itemize}
\item $A^\diamond = A$ si $A$ est une variable de type,
\item $(P\Rightarrow Q)^\diamond = (P^\diamond \Rightarrow \mathop{\sim}\mathop{\sim}Q^\diamond)$,
@@ -3609,25 +3683,27 @@ $\mathop{\sim}P := (P\Rightarrow Z)$, puis (inductivement) :
\smallskip
-\itempoint Il faut comprendre $\mathop{\sim}P$ comme « une
-continuation qui attend un type $P$ » et $\mathop{\sim}\mathop{\sim}P$
-comme « une valeur $P$ passée par continuation ».
-
-\smallskip
-
-\itempoint Noter que $x:P \;\vdash\; \lambda(k:\mathop{\sim}P).kx :
-\mathop{\sim}\mathop{\sim}P$ (transformation d'une valeur « directe »
-en valeur passée par continuation).
+\itempoint On pose enfin $P^{\cps} :=
+\mathop{\sim}\mathop{\sim}P^\diamond$ {\footnotesize (comprendre :
+ $\mathop{\sim}\mathop{\sim}(P^\diamond)$)}.
\smallskip
-{\footnotesize On si on préfère voir ça comme une fonction :
- $\lambda(x:P).\,\lambda(k:\mathop{\sim}P).\,kx$ a pour type $P
- \Rightarrow \mathop{\sim}\mathop{\sim}P$.\par}
+En gros :
+\begin{itemize}
+\item $P^\diamond$ est le type $P$ dans lequel toutes les fonctions
+ ont été réécrites en style CPS (= renvoient leurs valeurs par
+ continuation),
+\item $P^{\cps} := \mathop{\sim}\mathop{\sim}P^\diamond$ est le type
+ en question lui-même passé par continuation.
+\end{itemize}
\smallskip
-\itempoint On pose $P^{\cps} := \mathop{\sim}\mathop{\sim}P^\diamond$.
+{\footnotesize \itempoint Noter : $(P\Rightarrow Q)^{\cps} =
+ \mathop{\sim}\mathop{\sim}(P^\diamond \Rightarrow
+ \mathop{\sim}\mathop{\sim}Q^\diamond) =
+ \mathop{\sim}\mathop{\sim}(P^\diamond \Rightarrow Q^{\cps})$.}
%% {\footnotesize
%%
@@ -3652,31 +3728,44 @@ $\vdash t:P$ alors $\vdash t^{\cps}:P^{\cps}$ (rappel :
$\mathop{\sim}P := (P\Rightarrow Z)$ et $P^{\cps} :=
\mathop{\sim}\mathop{\sim}P^\diamond$) :
\begin{itemize}
-\item $v^{\cps} = \lambda k.kv$ si $v$ est une variable
-\item $(fx)^{\cps} = \lambda k.\,f^{\cps}(\lambda f_0.\,
- x^{\cps}(\lambda x_0.\, f_0 x_0 k))$
-\item $(\lambda v.t)^{\cps} =
- \lambda k.\, k(\lambda v.\, t^{\cps})$
-\item $\langle x,y\rangle^{\cps} = \lambda k.\, x^{\cps}(\lambda
- x_0.\, y^{\cps} (\lambda y_0.\, k\langle x_0,y_0\rangle))$
-\item $(\pi_i z)^{\cps} = \lambda k.\, z^{\cps}(\lambda z_0.\, k(\pi_i
- z_0))$ (pour $i\in\{1,2\}$)
-\item $(\iota_i z)^{\cps} = \lambda k.\, z^{\cps}(\lambda z_0.\,
- k(\iota_i z_0))$ (pour $i\in\{1,2\}$)
+\item $v^{\cps} = \lambda(k:\mathop{\sim}P^\diamond).\,kv$ lorsque $v$
+ est une variable de type $P$,
+\item $(fx)^{\cps} = \lambda (k:\mathop{\sim}Q^\diamond).\,
+ f^{\cps}(\lambda (f_0:P^\diamond\Rightarrow Q^{\cps}).\,
+ x^{\cps}(\lambda (x_0:P^\diamond).\, f_0 x_0 k))$ lorsque $f :
+ P\Rightarrow Q$ et $x : Q$ (rappel : $(P\Rightarrow Q)^{\cps} =
+ \mathop{\sim}\mathop{\sim}(P^\diamond \Rightarrow Q^{\cps})$),
+\item $(\lambda (v:P).t)^{\cps} = \lambda k.\, k(\lambda
+ (v:P^\diamond).\, t^{\cps})$ lorsque $\Gamma, v:P \vdash t:Q$,
+\item $\langle x,y\rangle^{\cps} = \lambda
+ (k:\mathop{\sim}(Q_1^\diamond \land Q_2^\diamond)).\,
+ x^{\cps}(\lambda (x_0:Q_1^\diamond).\, y^{\cps} (\lambda
+ (y_0:Q_2^\diamond).\, k\langle x_0,y_0\rangle))$,
+\item $(\pi_i z)^{\cps} = \lambda (k:\mathop{\sim} Q_i^\diamond).\,
+ z^{\cps}(\lambda (z_0:Q_1^\diamond\land Q_2^\diamond).\, k(\pi_i
+ z_0))$ (pour $i\in\{1,2\}$),
+\item $(\iota^{(Q_1,Q_2)}_i z)^{\cps} = \lambda
+ (k:\mathop{\sim}(Q_1^\diamond\lor Q_2^\diamond)).\, z^{\cps}(\lambda
+ (z_0:Q_i^\diamond).\, k(\iota^{(Q_1^\diamond,Q_2^\diamond)}_i z_0))$
+ (pour $i\in\{1,2\}$),
\item $(\texttt{match~}r\texttt{~with~}\iota_1 v_1 \mapsto t_1,\;
- \iota_2 v_2 \mapsto t_2)^{\cps} = \lambda k.\, r^{\cps}(\lambda
- r_0.\, (\texttt{match~}r_0\texttt{~with~}\iota_1 v_1 \mapsto
+ \iota_2 v_2 \mapsto t_2)^{\cps} = \lambda
+ (k:\mathop{\sim}Q^\diamond).\, r^{\cps}(\lambda
+ (r_0:P_1^\diamond\lor P_2^\diamond).\penalty0\,
+ (\texttt{match}\penalty500\ r_0\ \texttt{with}\ \iota_1 v_1 \mapsto
t_1^{\cps} k,\; \iota_2 v_2 \mapsto t_2^{\cps} k))$
-\item $\bullet^{\cps} = \lambda k.k\bullet$ \quad\itempoint
- $(\texttt{exfalso~} r)^{\cps} = \lambda k.\, r^{\cps}(\lambda r_0.\,
- (\texttt{exfalso~}r_0))$
+\item $\bullet^{\cps} = \lambda (k:\mathop{\sim}\top).k{\bullet}$
+\item $(\texttt{exfalso}^{(Q)} r)^{\cps} = \lambda
+ (k:\mathop{\sim}Q^\diamond).\, r^{\cps}(\lambda (r_0:\bot).\,
+ (\texttt{exfalso}^{(Q^\diamond)} r_0))$
\end{itemize}
-\itempoint Ajoutons : $\lambda(k:\mathop{\sim}(P\lor \mathop{\sim}
-P)).\, k(\iota_2^{(P,\mathop{\sim}
- P)}(\lambda(v:P).\,k(\iota_1^{(P,\mathop{\sim} P)} v)))$ de type
-$\mathop{\sim}\mathop{\sim}(P\lor \mathop{\sim} P)$, dont on tire
-facilement $(P\lor\neg P)^{\cps}$ (ceci donne par exemple le call/cc).
+\itempoint $\texttt{callcc}^{\cps} = \lambda (\ell:\cdots).\,
+\ell(\lambda (g : (P^\diamond \Rightarrow Q^{\cps}) \Rightarrow
+P^{\cps}).\, \lambda(k:\mathop{\sim}P^\diamond).\,
+g(\lambda(v:P^\diamond).\, \lambda(k_0:\mathop{\sim}Q^\diamond).\,
+kv)\,k)$, de type $(((P\Rightarrow Q)\Rightarrow P)\Rightarrow
+P)^{\cps}$.
\par}
@@ -3703,8 +3792,8 @@ l'ordre.
\medskip
\itempoint Le CPS donne le call/cc « pour rien ». En fait, en style
-CPS, chaque fonction a un contrôle complet sur l'exécution de tout le
-programme (puisqu'il n'y a plus de pile !).
+CPS, chaque fonction a contrôle complet sur l'exécution de tout le
+programme (il n'y a plus de pile !).
\medskip
@@ -3723,8 +3812,8 @@ notamment les promesses de JavaScript, et la monade
\frametitle{Continuation Passing Style : remarques logiques}
\itempoint Par la transformation $t \mapsto t^{\cps}$ et le fait
-d'avoir trouvé un terme de type $(P\lor\neg P)^{\cps}$, on a montré
-que :
+d'avoir trouvé un terme de type $(((P\Rightarrow Q)\Rightarrow
+P)\Rightarrow P)^{\cps}$, on a montré que :
\[
\text{si~}\mathsf{CPC} \vdash P\text{~alors~}\mathsf{IPC} \vdash P^{\cps}
\]
@@ -3735,7 +3824,7 @@ prouvable en logique classique ».
\medskip
\itempoint \alert{Si on prend $Z := \bot$}, la proposition $P^{\cps}$
-ajoute simplement des $\neg\neg$ un peu partout, ce qui ne change rien
+ajoute simplement des $\neg\neg$ un peu partout, ce qui est équivalent
en logique classique, donc on a évidemment
\[
\mathsf{CPC} \vdash P\text{~ssi~}\mathsf{CPC} \vdash P^{\cps}
@@ -3754,8 +3843,9 @@ traduction « double négation ».
{\footnotesize
\itempoint En fait, on peut se contenter de mettre un $\neg\neg$
-devant les disjonctions, ou même (en calcul \alert{propositionnel} !)
-d'en mettre un seul devant toute la formule.
+devant les disjonctions et formules atomiques (traduction de
+Gödel-Gentzen), ou bien (en calcul \alert{propositionnel} !) d'en
+mettre un seul devant toute la formule (traduction de Glivenko).
\par}