From 4aa877cd5cdf2609fa21b51a193d493a02342e76 Mon Sep 17 00:00:00 2001 From: Max New <maxsnew@gmail.com> Date: Sat, 7 Jul 2018 13:40:12 -0400 Subject: [PATCH] some notes on doing threesomes with cbpv --- notes/impl.tex | 221 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 notes/impl.tex diff --git a/notes/impl.tex b/notes/impl.tex new file mode 100644 index 0000000..11cd40e --- /dev/null +++ b/notes/impl.tex @@ -0,0 +1,221 @@ +\documentclass{article} + +\usepackage{float} +\usepackage{amsmath,amssymb, amsthm} +\usepackage{tikz-cd} +\usepackage{mathpartir} +\usepackage{rotating} +\usepackage{stmaryrd} + +\newtheorem{lemma}{Lemma} + +\renewcommand{\u}{\underline} +\newcommand{\kw}[1]{\texttt{#1}\,\,} + +\newcommand{\sem}[1]{\llbracket#1\rrbracket} +\newcommand{\dynv}{{?}} +\newcommand{\dync}{\u {\text{?`}}} +\newcommand{\ltdyn}{\sqsubseteq} +\newcommand{\gtdyn}{\sqsupseteq} +\newcommand{\equidyn}{\mathrel{\gtdyn\ltdyn}} +\newcommand{\dynmeet}{\sqcap} +\newcommand{\uarrow}{\mathrel{\rotatebox[origin=c]{-30}{$\leftarrowtail$}}} +\newcommand{\darrow}{\mathrel{\rotatebox[origin=c]{30}{$\twoheadleftarrow$}}} +\newcommand{\upcast}[2]{\langle{#2}\uarrow{#1}\rangle} +\newcommand{\dncast}[2]{\langle{#1}\darrow{#2}\rangle} +\newcommand{\case}{\kw{case}} +\newcommand{\pipe}{\,|\,} +\newcommand{\caseofXthenYelseZ}[3]{\case #1 \{ #2 \pipe #3 \}} +\newcommand{\bindXtoYinZ}[2]{\kw{bind} #2 \leftarrow #1;} +\newcommand{\ret}{\kw{ret}} +\newcommand{\err}{\mho} +\newcommand{\thunk}[1]{\{#1\}} +\newcommand{\force}{!} + +\begin{document} + +\title{Zig-zag Casts in Gradual Type Theory} +\author{Max S. New} + +\section{Reflecting on Type Dynamism} + +We translate GTT into a CBPV language extended with a pair of +connectives that model. +% +These come in two forms: the delayed upcast of a thunk $(U)$, and the +delayed downcast of a returner $(\u F)$. +% +In the contract translation, these cases are ``problematic''. +% +The upcast of a $U$ type introduces a proxy, for instance the cast +$\upcast{U(2 \to \u B)}{U(\dynv \to \u B)}$ is implemented as: +\[ +\sem{\upcast{U(2 \to \u B)}{U(\dynv \to \u B)}V} +\cong +\thunk{(\lambda (x:\dynv). \bindXtoYinZ {\dncast{\u F 2}{\u F \dynv}x} {(x':2)} \force V\, x')} +\] +% +which adds an indirection to the actual implementation. +% +In general, one indirection seems unavoidable, but worse is that a +sequence of upcasts of the same thunk will result in a linear number +of indirections. +% +Dually, the downcast of a $\u F$ type is a \emph{non-tail} call, for +instance the cast $\dncast{\u F 2}{\u F \dynv}$ is, in the natural and +Scheme-like interpretations, implemented as a case-analysis: +\[ \sem{\dncast{\u F 2}{\u F \dynv}M} \cong +\bindXtoYinZ M x +\caseofXthenYelseZ x {\texttt{in}_2 x_2. \ret x_2}{\texttt{else}. \err} +\] +if $M$ is a tail call, then this downcast breaks the tail call, +because we need $M$ to return to the cast, which then performs the +case-analysis and returns. +% +Adding one return indirection like this seems unavoidable, but worse +is that a sequence of downcasts of $\u F$ types results in a linear +number of indirections. + +Essentially these are the same/dual problems, and we solve them with +the same/dual solution. +% +The basic idea is to consider the $U$ type of GTT \emph{not} to be a +type of thunks, but \emph{delayed casts of thunks}. +% +That is, a value of type $U \u B$ in GTT is not necessarily +represented by a $U \u B$ at runtime, but rather some original type +$\u B_i$ (i for implementation) that has been casted to $U\u B$, +\emph{via} some type $\u B_m$ (m for middle). +% +This is a ``threesome cast'' (which I will refer to as a zig-zag cast +because it is more descriptive: we cast down and then up), the use of +a middle type allows us to ``summarize'' a sequence of casts into a +single pair of casts. +% +Thus in general the cast through the middle type will be +\emph{stronger} than the direct cast: otherwise we wouldn't need the +middle type at all. +% +We can represent this as a \emph{dependent pair}: +\[ \sem{U \u B} = \sum_{\u Y \ltdyn \u B} \sum_{\u Y' \gtdyn \u Y} U\u Y' \] +% +Then a thunk is implemented by instantiating $\u Y$ with $\u B$ (using +reflexivity): +\[ +\sem{{\thunk M}_{\u B}} = (\u B \ltdyn \u B, \u B\gtdyn \u B, \thunk M) +\] +Forcing a proxied thunk is implemented by running the implementation +of the zig zag of casts (which can be interpreted on the fly or a jump +to a predetermined implementation): +\[ +\sem{\force} (\u Y \ltdyn \u B, \u Y' \gtdyn \u Y, V : U\u Y') = \force \sem{\upcast{U\u Y}{U\u B}}\thunk {\sem{\dncast{\u Y}{\u Y'}}\force V} +\] +Finally, we compose with casts. +% +An upcast of a thunk is trivial: just replace $B$ with $B'$. +% +\[ \sem{\upcast{U B}{U B'}}(Y \ltdyn B, Y' \gtdyn Y, V) = +(Y \ltdyn B', Y' \gtdyn Y, V) +\] +A downcast of a thunk does the real computation: we replace the middle +type $Y$ with the \emph{meet} of $Y$: +\[ \sem{\dncast{U B}{U B'}(Y \ltdyn B', Y' \gtdyn Y, V)} += (Y \dynmeet B \ltdyn B, Y' \gtdyn Y \dynmeet B, V) \] + +Dually, for $\u F$ types, we want the \emph{stacks} out of a $\u F$ +type to be delayed casts. +% +We translate a $\u F A$ term to a term that will perform a zig-zag +cast when told which one to do, or in other words it expects the +\emph{stack} to provide it a zig-zag. +% +We can represent this as a \emph{dependent function}: +\[ \sem{\u F A} = \prod_{X \ltdyn A}\prod_{X' \gtdyn X} \u F X' \] +A bind out of $\u F A$ is implemented by instantiating $X$ with $A$ +itself, using reflexivity of dynamism: +\[ \sem{\bindXtoYinZ {M : \u F A} {x} {N}} = \bindXtoYinZ {M\,(A \ltdyn A)\,(A\ltdyn A)} x N \] +Return is implemented by running the zigzag cast on the stack: +\[ \sem{\ret{}} (V : A) = \lambda (X \ltdyn A) \lambda (X' \gtdyn X). +\bindXtoYinZ {\sem{\dncast{\u F X}{\u F A}} \ret V} x \upcast{X}{X'} x \] + +The downcast is trivial, using transitivity of dynamism. +\[ +\sem{\dncast{\u F A}{\u F A'}}[M]\,(X\ltdyn A)\,(X'\gtdyn X) += +M\,(X \ltdyn A \ltdyn A')\,(X' \gtdyn X) +\] +The upcast does the work, computing the meet: +\[ +\sem{\upcast{\u F A}{\u F A'}}[M]\,(X \ltdyn A')\,(X'\gtdyn X) += +M\,(X \dynmeet A \ltdyn A)\,(X' \gtdyn X \gtdyn X \dynmeet A) +\] + +We can model cast \emph{failure} by adding rules that $0, \top$ are +least value and computation types respectively. + +%% \begin{figure} +%% \begin{mathpar} +%% \begin{array}{lcl} +%% A & \bnfdef & X \mid \mu X.A \mid U \u B \mid 0 \mid A_1 + A_2 \mid 1 \mid A_1 \times A_2 \\ +%% \u B & ::= & \u Y\mid \nu \u Y. \u B \mid \u F A \mid \top \mid \u B_1 \with \u B_2 \mid A \to \u B\\ +%% \Gamma & ::= & \cdot \mid \Gamma, x : A \\ +%% \Delta & ::= & \cdot \mid \bullet : \u B \\ +%% V & ::= & x \mid \rollty{\mu X.A}V \mid \inl{V} \mid \inr{V} \mid \\ +%% & & () \mid (V_1,V_2)\mid \thunk{M} +%% \\ +%% M & ::= & \err_{\u B} \mid \letXbeYinZ V x M \mid \pmmuXtoYinZ V x M \mid \rollty{\nu \u Y.\u B} M \mid \unroll M \mid \abort{V} \mid \\ +%% & & \caseofXthenYelseZ V {x_1. M_1}{x_2.M_2} \mid \pmpairWtoinZ V M \mid \pmpairWtoXYinZ V x y M +%% \mid \force{V} \mid \\ +%% & & \ret{V} \mid \bindXtoYinZ{M}{x}{N} \mid \lambda x:A.M \mid M\,V \mid \emptypair \mid \pair{M_1}{M_2} \mid \pi M \mid \pi' M +%% \\ +%% S & ::= & \bullet \mid \bindXtoYinZ S x M \mid S\, V \mid \pi S \mid \pi' S +%% \end{array} +%% \end{mathpar} +%% \caption{Operational GTT Syntax} +%% \end{figure} + +\section{Correctness} + +We can show the correctness of this translation by showing that it +\emph{simulates} the inefficient semantics. + +That is for any GTT type $T$ we can implement total ``wrapper'' +functions $T \Rightarrow \sem T$ and $\sem T \Rightarrow T$ with the +property that for every term $\Gamma\pipe\Delta \vdash E : T$ +implemented in GTT, $E$ is equivalent to composing +$\sem\Gamma\pipe\sem\Delta \vdash \sem E : \sem T$ with the wrappers. + +To prove this, the main lemma would be to prove +\begin{lemma}[Correctness of Zigging through Meets] + {~} + \begin{enumerate} + \item For every zig-zag-zig $A_2' \gtdyn A_2 \ltdyn A_1' \gtdyn A_1$ + the cast sequence + \[ \upcast{\u F A_2}{\u F A_2'}\dncast{\u F A_2}{\u F A_1'}\upcast{\u F A_1}{\u F A_1'} \] + is equivalent ($\equidyn$) to the single zig-zag: + \[ \upcast{\u F (A_2 \dynmeet A_1)}{\u F A_2'}\dncast{\u F (A_2 \dynmeet A_1)}{\u F A_1} \] + \item For every $B_1 \ltdyn B_1' \gtdyn B_2 \ltdyn B_2'$ + the cast sequence + \[ \dncast{UB_1}{UB_1'}\upcast{UB_2}{UB_1'}\dncast{UB_2}{UB_2'} \] + is equivalent to the single zig-zag: + \[ \upcast{U(B_1 \dynmeet B_2)}{UB_1}\dncast{U(B_1 \dynmeet B_2)}{UB_2'} \] + \end{enumerate} +\end{lemma} + +Which seems to want the following universal property of meets: +\begin{lemma}[Meets turn a Zag-zig into a Zig-zag] + {~} + \begin{enumerate} + \item For any $A_1, A_2$, the cast through $\dynv$: + \[ \dncast{\u F A_1}{\u F \dynv}\upcast{\u F A_2}{\u F \dynv} \] + is equivalent to the cast through $\u F(A_1 \dynmeet A_2)$: + \[ \upcast{\u F (A_1 \dynmeet A_2)}{\u F A_1}\dncast{\u F (A_1 \dynmeet A_2)}{\u F A_2} \] + \item For any $B_1, B_2$, the cast through $\dync$: + \[ \dncast{U B_1}{U\dync}\upcast{UB_2}{U\dync} \] + is equivalent to the cast through $B_1 \dynmeet B_2$: + \[ \upcast{U(B_1\dynmeet B_2)}{UB_1}\dncast{U(B_1\dynmeet B_2)}{UB_2} \] + \end{enumerate} +\end{lemma} + +\end{document} -- GitLab