\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}
