\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{amsthm}
\usepackage{proof}
\usepackage{mathpartir}
\usepackage{url}
\usepackage{listings}
\usepackage{color}
\definecolor{eclipseBlue}{RGB}{42,0.0,255}
\definecolor{eclipseGreen}{RGB}{63,127,95}

\lstset {
  basicstyle=\small\ttfamily,
  captionpos=b,
  tabsize=2,
  columns=fixed,
  breaklines=true,
  frame=l,
  numbers=left,
  numberstyle=\small\ttfamily,
  morekeywords= {
    EQUAL, GREATER, LESS, NONE, SOME, abstraction, abstype, and, andalso, array, as, before, bool, case, char, datatype, do, else, end, eqtype, exception, exn, false, fn, fun, functor, handle, if, in, include, infix, infixr, int, let, list, local, nil, nonfix, not, o, of, op, open, option, orelse, overload, print, raise, real, rec, ref, sharing, sig, signature, string, struct, structure, substring, then, true, type, unit, val, vector, where, while, with, withtype, word
  },
  morestring=[b]",
  morecomment=[s]{(*}{*)},
  stringstyle=\color{black},
  identifierstyle=\color{eclipseBlue},
  keywordstyle=\color{red},
  commentstyle=\color{eclipseGreen}
} 

\newtheorem{theorem}{Theorem}

\newcommand{\texttilde}{\url{~}}
\newcommand{\step}{\stackrel{1}{\Longrightarrow}}
\newcommand{\stepk}[1]{\stackrel{#1}{\Longrightarrow}}

\title{Lecture 5 - A First Look at Custom Types}
\author{David M Kahn}
\date{Summer 2022}

\begin{document}

\maketitle

\section{Custom Types}

\subsection{Why}

One of the most common activities in SML-style functional programming 
is creating one's own types to logically structure the data one 
will be working with in their code. This is because,
as we have emphasized before, the type of data 
dictates how to compute with it. Once one works out 
the most logical structure of the data they want to 
compute with, one basically has a
template for the code interacting with that data!

On the flip side,
defining our own types can prevent data from being computed 
with incorrectly. This keeps our code bug-free.
For instance, consider the following function \texttt{indexOf},
which is a common sort of operation to see in other languages.

\begin{lstlisting}
(*
 * indexHelp: int list * int * int -> int
 * REQUIRES: true
 * ENSURES: indexHelper (lst, n, acc) evaluates to 
 *  acc + the first index at which n appears
 *  in lst (0-indexed), or ~1 if n does not appear in lst
 *)
fun indexHelp (lst:int list, n:int, acc:int) : int = 
  (case lst of
      [] => ~1 
    | x::xs => 
      if x = n 
      then acc 
      else indexHelp (xs, n, acc + 1)
  )

(*
 * indexOf: int list * int -> int
 * REQUIRES: true
 * ENSURES: indexOf (lst, n) evaluates to 
 *  the first index at which n appears
 *  in lst (0-indexed), or ~1 if n does not appear in lst
 *)
fun indexOf (lst:int list, n:int) : int = 
  indexHelp (lst, n, 0)
\end{lstlisting}

Because this function returns always returns an 
\texttt{int}, the failure case where 
the input list does not contain \texttt{n} 
is silent. Our hidden 
mental meaning of \texttt{\texttilde1} as failure 
can be missed, and one can accidentally begin to 
perform arithmetic with the \texttt{\texttilde1} that 
the function returns, rather than handling it appropriately.

\subsection{SML Usage}

To define a custom type, one uses 
the following sort of \textit{declaration}\footnote{
  The order of the constructors doesn't matter.
  Also note that the first letters of constructors 
  in SML are usually capitalized, and in fact 
  usually all the letters of constructors are capitalized.
}, where the name of 
the type \texttt{name} is recursively bound for use 
in any type \texttt{ti}.
\\
\\
\texttt{datatype name = C1 | C2 | ... | Cn | Cm of tm | ... 
| Cp of tp}
\\
\\
This declaration defines a new type \texttt{name} that 
can come in various different forms depending on the 
\texttt{Ci} we put in its definition. For this reason,
the kind of data this type describes is called a 
\textit{variant}. Each of these \texttt{Ci} is called a(n inductive) constructor, 
which calls back to the list constructors cons \texttt{::}
and nil \texttt{[]} we looked at before. 

There are actually a lot of different names for 
the kind of type that this declaration defines, including 
\textit{sum, coproduct, choice, enum}, and others mentioned 
below. Further, because one can recursively (inductively)
refer to the type itself in one of its constructors, 
this allows the definition of recursive (inductive) 
types.

You will notice 
that there are two kinds of constructors we may choose 
to use in the declaration above: 
the constant constructors that stand alone, and 
the constructors that are \textit{of} some 
other type \texttt{ti}. In the first case, the 
constructor \textit{is itself} a value of the defined type,
and in the second case the constructor is more like a 
tag or label paired with values of the type \texttt{ti}.

The number of pieces of data that a constructor tags is 
called its \textit{arity}, so the constant constructor is 
of arity 0, and the other constructors have arity 1.
We can simulate higher arities by having the constructor tag
a product of multiple types. Sometimes we even just call 
the number of elements in that product the arity. This same terminology 
us also used for the number 
of arguments a function takes.

The point of labelling with these constructors
is that these constructors are something 
we can pattern match on. This allows us to discriminate 
between the different cases of the variant type 
we have defined just by checking the tag. For this reason, this kind of 
type can further be called a \textit{tagged} or \textit{discriminated union}.
It can also be called a \textit{disjoint union} since,
even if two constructors are tagging the same type, 
the the differently tagged values are distinct (disjoint) from 
one another.

An additional effect of declaring constructors of 
arity 1 is that SML will allow you to use those 
constructors like functions that map into the 
defined type. For example, \texttt{Cm:tm -> name} 
is created from the above declaration. Nonetheless, these 
are not your standard sort of functions, since 
they can be pattern-matched. Nor do they ``apply" in 
the same sense, since \texttt{Cm v} is already a value.

Note that because these types are defined through declaration,
they may also be locally scoped in a let statement like any 
other declaration. However, there is rarely a reason to 
prefer a local scope over a global (top-level) scope for type 
definitions.

SML also comes with a pre-declared
sum type, \texttt{order}, made up of the 
three constant constructors 
\texttt{GREATER, EQUAL,} and \texttt{LESS}. These 
are meant to be used to indicate 
the logical result 
of a comparison. Other languages 
sometimes have comparison functions 
return $1, 0,$ or $-1$
for the same purpose, but this 
runs the buggy code risk described above 
since integers may be computed with in many ways.


One final note about these declarations is to avoid
the reuse of constructors within the same declaration and
between declarations. SML will naturally shadow 
them and make it difficult to refer to the shadowed 
constructor. SML will not easily disambiguate 
the use of the constructor based on the expected type.

\subsection{Patterns}

One makes use of the distinguishing features of 
the sum type by pattern matching. To do so, 
constructors are added to the kinds of patterns 
we can create. The general 
form of these patterns can be exemplified in the sort 
of case expression below, where \texttt{pm} refers to a 
pattern appropriate for type \texttt{tm}:
\\
\\
\texttt{case v of C1 => e1 | ... | Cm pm => em | ...}
\\
\\
Notice how the word ``of'' is \textit{not} part of 
the pattern, but the constructor \textit{is}.

One further addition we can make to our collection of 
patterns is the following, where each \texttt{pi} is 
a pattern:
\\
\\
\texttt{(p1 | p2 | ... | pn)}
\\
\\
This pattern matches any value that matches one of its 
contained patterns \texttt{pi}. Now that we may have 
types with many constructors, this kind 
of pattern has some real utility. For instance,
when casing, if multiple 
constructors of a variant should be treated identically,
we may collect them all using this pattern and write 
the case for them only once. We will see examples of 
this in later subsections.

In total then, here is our collection of patterns so far:
\begin{itemize}
  \item constants (not functions or reals)
  \item variables 
  \item the underscore wildcard \_
  \item tuples of other patterns \texttt{(p1, p2, ..., pn)}
  \item the constant list constructor nil \texttt{[]}
  \item the inductive list constructor cons applied to other patterns \texttt{p1::p2}
  \item constant constructors of declared types \texttt{C}
  \item other constructors of declared types \texttt{C}
  tagging another pattern \texttt{C p}
  \item choices between patterns \texttt{(p1 | p2 | ... | pn)}
\end{itemize}

\subsection{Examples}

Here is an example using a type for colors, which 
also saves us from rewriting code by using one of our 
new patterns:

\begin{lstlisting}
datatype color = RED | YELLOW | BLUE 
  | ORANGE | PURPLE | GREEN

(*
 * isWarm: color -> bool
 * REQUIRES: true
 * ENSURES: isWarm c ==> the bool indicating if 
 *  c represents a warm color
 *)
fun isWarm c = 
  (case c of 
      (RED | YELLOW | ORANGE) => true
    | _ => false
  )
\end{lstlisting}

Here is an example showing us the option type for 
integers, which would be a better type to use 
for the return of the function \texttt{indexOf} 
from earlier:

\begin{lstlisting}
datatype intOption = NONE | SOME of int

(*
 * indexOf: int list * int -> int
 * REQUIRES: true
 * ENSURES: indexOf (lst, n) evaluates to 
 *  the first index at which n appears
 *  in lst (0-indexed), or ~1 if n does not appear in lst
 *)
fun indexOf (lst:int list, n:int) : intOption =
  (case lst of 
      [] => NONE
    | x::xs => 
      if x = n 
      then SOME 0 
      else
      (case indexOf (tl, n) of
          NONE => NONE 
        | SOME i => SOME (i + 1)
      )
  )
\end{lstlisting}

Here is a way to simulate the type of integer lists 
using the recursive binding of the type's name:

\begin{lstlisting}
datatype intList = NIL | CONS of int * intList

(*
 * len : intList -> int
 * REQUIRES: true
 * ENSURES: len lst ==> the number of CONS 
 *  constructors in lst
 *)
fun len (lst:intList) : int = 
  (case lst of 
      NIL => 0
    | CONS (x, xs) => 1 + len xs
  )
\end{lstlisting}

Here is a way to simulate a list holding more 
than one type of data, by wrapping the 
data in a sum type:
\begin{lstlisting}
datatype intOrBool = INT of int | BOOL of bool 

(*
 * intCount : intOrBool list -> int
 * REQUIRES: true
 * ENSURES: intCount lst ==> the number of int 
 *  elements in lst
 *)
fun intCount (lst:intOrBool list) : int =
  (case lst of 
      [] => 0
    | (INT _)::tl => 1 + intCount tl 
    | _::tl => intCount tl
  )
\end{lstlisting}

Here is an example defining a binary tree of 
integers:

\begin{lstlisting}
datatype intTree = LEAF | NODE of intTree * int * intTree

(*
 * depth : intTree -> int
 * REQUIRES: true
 * ENSURES depth t ==> the depth of t
 *)
fun depth (t:intTree) : int =
  (case t of 
      LEAF => 0
    | NODE (l, _, r) => 
      let 
        dl = depth l
        dr = depth r
      in 
        if dl > dr
        then dl 
        else dr
      end
  )
\end{lstlisting}

Here is a more complicated tree example 
with more kinds of nodes -- the expression 
tree for basic arithmetic:
\begin{lstlisting}
datatype mathExp = 
    NUM of int 
  | PLUS of mathExp * mathExp 
  | TIMES of mathExp * mathExp
  | MINUS of mathExp * mathExp
  | DIV of mathExp * mathExp
  | NEG of mathExp

(*
 * calc : mathExp -> int
 * REQUIRES: true
 * ENSURES: calc e ==> the integer e represents 
 *  or throws a divide by 0 exception 
 *  if the expression divides by 0 anywhere
 *)
fun calc (e:mathExp) : int = 
  (case e of 
      NUM n => n 
    | PLUS (e1, e2) => (calc e1) + (calc e2)
    | TIMES (e1, e2) => (calc e1) * (calc e2)
    | MINUS (e1, e2) => (calc e1) - (calc e2)
    | DIV (e1, e2) => (calc e1) div (calc e2)
    | NEG e' => ~ (calc e') 
  )
\end{lstlisting}

\subsection{Feature Summary}

\paragraph{Values} 
\begin{itemize}
  \item \texttt{C} for each constant constructor \texttt{C}
  \item \texttt{C} $v$ for each constructor \texttt{C of t} 
  where $v$ is a value of type \texttt{t}. 
\end{itemize} 

\paragraph{Expressions}
\begin{itemize}
  \item Make: 
  \begin{itemize}
    \item \texttt{C} for each constant constructor \texttt{C} 
    \item \texttt{C} $e$ for each constructor \texttt{C of t} 
    where $e$ is an expression of type \texttt{t}
  \end{itemize}

  \item Use: pattern matching in a case statement
\end{itemize}

\paragraph{Typing}
\begin{itemize}
  \item Make: 
  \begin{itemize}
    \item \texttt{C:}$t$ when \texttt{C} is declared as 
    a constant constructor of $t$ 

    \item \texttt{C} $e$\texttt{:}$t$ when \texttt{C of t'} is part 
    of $t$'s declaration, and $e$\texttt{:t'}
  \end{itemize}
  \item Use: the usual typing of case statements
\end{itemize}

\paragraph{Reduction}
\begin{itemize}
  \item Make: 
  \begin{itemize}
    \item \texttt{C} is a value for each constant constructor \texttt{C},
    and it does not reduce

    \item \texttt{C} $e \step$ \texttt{C} $e'$ if $e \step e'$
  \end{itemize}
  \item Use: the usual reduction of case statements
\end{itemize}




\subsection{Structural Induction}

Each datatype we declare comes with its 
own induction principle, and it follows the 
same idea as described in previous 
lecture notes: constructors that 
don't recursively use their type 
are the base cases, and those that do 
are the inductive steps.

Let's use the type \texttt{intTree} from 
the above section as an example. The basic induction 
principle for \texttt{intTree} is that 
if 
\begin{itemize}
  \item P(\texttt{LEAF}) holds
  \item P(\texttt{NODE (l,n,r)}) 
  assuming P(\texttt{l}) and P(\texttt{r})
  for values \texttt{l:intTree}, \texttt{r:intTree}, 
  \texttt{n:int}
\end{itemize}
then P(\texttt{t}) holds for any value
\texttt{t:intTree}. 

As before, these principles come in
strong and general variants as well.

Now we will use this induction principle
in an example proof.

\begin{theorem}
  \texttt{depth} is total
\end{theorem}
\begin{proof}
  We show the totality of \texttt{depth} by 
  showing \texttt{depth t} is valuable for 
  every value \texttt{t:intTree}. We show 
  this fact by induction on \texttt{t}.

  \paragraph{Base Case} \texttt{t = LEAF}
  \begin{align*}
    \mathtt{depth} \; \mathtt{LEAF} \; \Longrightarrow \; & 0 
    & \textrm{clause 1}
    \\
    \hookrightarrow & 0 & \textrm{0 is value}
  \end{align*}

  \paragraph{Inductive Step} \texttt{t = NODE (l,n,r)}
  We assume that \texttt{depth l} and \texttt{depth r} 
  are both valuable. Let them evaluate to $\mathtt{v_l}$ 
  and $\mathtt{v_r}$ respectively.
  \begin{align*} 
    \mathtt{depth}\;\mathtt{NODE (l,n,r)} \; \Longrightarrow \; 
    &\mathtt{if \; v_l > v_r \;then \;v_l \;else \;v_r}
    & \textrm{IH \& clause 2}
    \\
    \; \Longrightarrow \;& \mathtt{if \; v_b \;then \;v_l \;else \;v_r}
    & > \textrm{totality}
  \end{align*}
  We now continue the reduction by cases over $\mathtt{v_b}$
  \begin{itemize}
    \item case $\mathtt{v_b = true}$
    \begin{align*}
      \; \Longrightarrow \; & \mathtt{v_l} & 
      \textrm{then clause}
      \\
      \hookrightarrow &  \mathtt{v_l} &  \mathtt{v_l} \textrm{is value}
    \end{align*}

    \item case $\mathtt{v_b = false}$
    \begin{align*}
      \; \Longrightarrow \; & \mathtt{v_r} & 
      \textrm{then clause}
      \\
      \hookrightarrow &  \mathtt{v_r} &  \mathtt{v_r} \textrm{is value}
    \end{align*}
  \end{itemize}
\end{proof}

\section{Mutual Recursion/Induction}

One tool we can make use of,
both with types and functions, 
is mutual recursion. This is where 
multiple declarations may refer to
each other recursively in their 
definitions. This idea will not 
be used much now, so we will only 
briefly explain them here. However, 
it will come 
up again later in the course.

For both types and functions, 
mutual recursion is introduced by 
replacing the next declaration keyword 
with \texttt{and}.

Here are two mutually recursive types for 
lists that alternate element types between 
\texttt{int} and \texttt{bool}, and 
two mutually recursive functions for the 
length of such lists.

\begin{lstlisting}
datatype intBoolList = IBNIL | IBCONS of int * boolIntList 
and boolIntList = BINIL | BICONS of bool * intBoolList

(*
 * ibLen : intBoolList -> int
 * REQUIRES: true
 * ENSURES: ibLen lst ==> the length of lst
 *)
fun ibLen (lst:intBoolList) : int = 
  (case lst of 
      IBNIL => 0
    | IBCONS (_,bis) => 1 + biLen bis
  )
(*
 * biLen : boolIntList -> int
 * REQUIRES: true
 * ENSURES: biLen lst ==> the length of lst
 *)
and biLen (lst:boolIntList) : int =
  (case lst of 
      BINIL => 0
    | BICONS (_,ibs) => 1 + ibLen ibs
  )
\end{lstlisting}

Mutual recursion can always be unentwined. 
The morally equivalent stand-alone version of 
\texttt{intBoolList} and its length function 
are given by the following:

\begin{lstlisting}
datatype intBoolList = IBNIL | INT of int 
  | IBCONS of int * bool * intBoolList

(*
 * ibLen : intBoolList -> int
 * REQUIRES: true
 * ENSURES: ibLen lst ==> the length of lst
 *)
fun ibLen (lst:intBoolList) : int = 
  (case lst of 
      IBNIL => 0
    | INT _ => 1
    | IBCONS (_,_,ibs) => 2 + ibLen ibs
  ) 
\end{lstlisting}

Even though it can be unentwined, notice 
that the resulting type definition and 
function are a little larger -- mutual 
recursion can be more succinct.

To reason about mutual recursion, there 
is a also a more direct form of induction: 
mutual induction. To perform this kind 
of induction, you split your predicate 
into two -- one for each of the two 
mutual recursive functions/types. For natural numbers (from which 
we can derive the structural induction principle), 
the induction looks like this:

if 
\begin{itemize}
  \item P(0) and Q(0) hold 
  \item P($n+1$) and Q($n+1$) hold assuming 
  P($n$) and Q($n$)
\end{itemize}
then P($n$) and Q($n$) both hold for all $n$. 
This has strong and general variants as well.

It is also possible to have more than 2 
types and functions mutually recur -- 
simply continue to use \texttt{and} to 
declare more. These have corresponding 
mutual induction principles.


\end{document}