gdritter repos documents / master duality / duality.tex
master

Tree @master (Download .tar.gz)

duality.tex @masterraw · history · blame

\documentclass{scrartcl}
\usepackage[letterpaper]{geometry}
\usepackage{fullpage}
\usepackage{cmbright}
\usepackage[usenames,dvipsnames]{color}
\usepackage{listings}
% \newcommand{\both}[2]{\begin{tabular}{ p{4in} p{4in} } #1 && #2 \\ \end{tabular}}
\newcommand{\pos}[1]{\textcolor{BrickRed}{#1}}
\newcommand{\postt}[1]{\textcolor{BrickRed}{\texttt{#1}}}
\newcommand{\dual}[1]{\textcolor{NavyBlue}{#1}}
\newcommand{\dualtt}[1]{\textcolor{NavyBlue}{\texttt{#1}}}
\newenvironment{both}
  { \begin{tabular}{ p{3in}  p{3in} } }
  { \\ \end{tabular} }

\renewcommand{\ttdefault}{pcr}
\lstset{basicstyle=\ttfamily,columns=flexible,language=[LaTeX]TeX,%
        texcl,%set comments in an extra line
        mathescape=false,escapechar=|,
literate={data}{\bfseries\textcolor{BrickRed}{data }}1
         {codata}{\bfseries\textcolor{NavyBlue}{data }}1
         {record}{\bfseries\textcolor{NavyBlue}{record }}1
         {case}{\bfseries\textcolor{BrickRed}{case }}1
         {of}{\bfseries\textcolor{BrickRed}{of }}1
         {merge}{\bfseries\textcolor{NavyBlue}{merge }}1
         {from}{\bfseries\textcolor{NavyBlue}{from }}1
         {if}{\bfseries{if }}1
         {then}{\bfseries{then }}1
         {else}{\bfseries{else }}1
         {assert}{\bfseries{assert }}1
         {<+>}{{+ }}1
         {+}{\textcolor{BrickRed}{+ }}1
         {*}{\textcolor{NavyBlue}{* }}1
         {<pos>}{\color{BrickRed}}1
         {</pos>}{\normalcolor}1
         {<dual>}{\color{NavyBlue}}1
         {</dual>}{\normalcolor}1
         ,%
         texcsstyle=*\color{blue!70}\bfseries,
         texcs={end,begin,documentclass}
}
\begin{document}
\section{\pos{Data} and \dual{Codata}}

\begin{both}
    \pos{Data} is defined by its \pos{introduction} rules.
  & \dual{Codata} is defined by its \dual{elimination} rules.
\\
    We can define a \pos{data} type with
  & We can define a \dual{codata} type with
\\
  \begin{lstlisting}
  data <pos>Either</pos> a b
    = Left  a
    + Right b
  \end{lstlisting}
  &
  \begin{lstlisting}
  codata <dual>Both</dual> a b
    = first  a
    * second b
  \end{lstlisting}
\\
    This definition will effectively introduce two functions:
  & This definition will effectively introduce two functions:
\\
  \begin{lstlisting}
  Left  : a -> <pos>Either</pos> a b
  Right : b -> <pos>Either</pos> a b
  \end{lstlisting}
&
  \begin{lstlisting}
  first  : <dual>Both</dual> a b -> a
  second : <dual>Both</dual> a b -> b
  \end{lstlisting}
\\
    In order to \pos{destruct data} we have to use
    \pos{patterns} which let you match on \pos{constructors}.
  & In order to \dual{construct codata} we have to use
    \dual{copatterns} which let you match on \dual{destructors}.
\\
  \begin{lstlisting}
  case e of
     Left  x -> e1
     Right y -> e2
  \end{lstlisting}
&
  \begin{lstlisting}
  merge x from
     first  x <- e1
     second x <- e2
  \end{lstlisting}
\\
    Here, \postt{e} represents the \pos{value being
    destructed}, and each branch represents a \pos{constructor
    with which it might have been constructed}. We are effectively
    \pos{dispatching on possible pasts} of
    \postt{e}.
  & Here, \dual{\texttt{x}} represents the \dual{value being
    constructed}, and each branch represents a \dual{destructor
    with which it might eventually be destructed}. We are effectively
    \dual{dispatching on possible futures} of
    \dualtt{x}.
\\
\end{both}

\section{Codata, Records, and Copatterns}
\raggedright

In the same way that named sums are a natural way to represent data,
records are a natural way to represent codata. In lieu of the above
syntax, one often sees codata represented as something more like

\begin{lstlisting}
record <dual>Both</dual> a b = <dual>{</dual> .first : a, .second : b <dual>}</dual>

x : <dual>Both</dual> Int Bool
x = <dual>{</dual> .first = 2, .second = true <dual>}</dual>

assert x.first == 2
assert x.second == true
\end{lstlisting}

The \dualtt{merge} syntax is used here for conceptual
symmetry with \postt{case}. Additionally, the use of
copatterns is nicely dual with the extra expressivity that
patterns offer. For example, we can use nested patterns with
constructors of various types, as in this function which
processes a list of \postt{Either Int Bool} values
by summing the integers in the list until it reaches a
\postt{false} value or the end of the list:

\begin{lstlisting}
f : List (Either Int Bool) -> Int
f lst = case lst of
  Cons (Left i) xs  -> i <+> f xs
  Cons (Right b) xs -> if b then f xs else 0
  Nil               -> 0
\end{lstlisting}

Similarly, we can define an infinite stream of pairs using
nested copatterns as so:

\begin{lstlisting}
s : Int -> Stream (Both Int Bool)
s n = merge x from
  first (head x)  <- n
  second (head x) <- n > 0
  tail x          <- x
\end{lstlisting}

Copatterns are also practically expressive, as in this concise
and readable definition of the fibonacci numbers in terms of
the \dualtt{merge} expression:

\begin{lstlisting}
codata Stream a
  = head a
  * tail (Stream a)

zipWith : (a -> b -> c) -> Stream a -> Stream b -> Stream c
zipWith f s1 s2 = merge x from
  head x <- f (head s1) (head s2)
  tail x <- zipWith f (tail s1) (tail s2)

fibs : Stream Int
fibs = merge x from
  head x        <- 0
  head (tail x) <- 1
  tail (tail x) <- zipWith (<+>) x (tail x)
\end{lstlisting}

\section{Row-Typed \dual{Co}data}

\begin{both}
    It is possible to build an \pos{open sum} by a small
    modification of the datatype mechanism. Instead of
    naming types and listing their associated
    \pos{constructors}, we represent a type as a
    \pos{list of constructors and types}.
  &
    It is possible to build an \dual{open product} by a small
    modification of the datatype mechanism. Instead of
    naming types and listing their associated
    \dual{destructors}, we represent a type as a
    \dual{list of destructors and types}.
\\
  {\color{BrickRed}
\begin{verbatim}
{- .. -} : [ Left: a + Right: b ]
\end{verbatim}
  }
  &
  {\color{NavyBlue}
\begin{verbatim}
{- .. -} : { first: a * second: b }
\end{verbatim}
  }
\\
    Use of a \pos{constructor} no longer specifies a
    specific type, but rather \pos{any type that can be
    constructed with that constructor}.
  &
    Use of a \dual{destructor} no longer specifies a
    specific type, but rather \dual{any type that can be
    destructed with that destructor}.
\\
\begin{lstlisting}
Left  : a -> <pos>[</pos> Left: a + ... <pos>]</pos>
Right : b -> <pos>[</pos> Right: b + ... <pos>]</pos>
\end{lstlisting}
  &
\begin{lstlisting}
first  : <dual>{</dual> first: a * ... <dual>}</dual> -> a
second : <dual>{</dual> second: b * ... <dual>}</dual> -> b
\end{lstlisting}
\\
    If we want to \pos{destruct} an open value like this, we
    can use a \postt{case} construct, as before.
  &
    If we want to \dual{construct} an open value like this, we
    can use a \dualtt{merge} construct, as before.
\\
  {\color{BrickRed}
\begin{verbatim}
f : [ Left Int + Right Bool ] -> Int
f e = case e of
        Left  i -> i
        Right b -> if b then 1 else 0
\end{verbatim}
  }
  &
  {\color{NavyBlue}
\begin{verbatim}
f : Int -> { First Int * Second Bool }
f i = merge x from
        first  x <- i
        second x <- i == 0
\end{verbatim}
}
\end{both}
\end{document}