

\pagebreak
\begin{exercise}{}

  Consider the following definition for a recursive function \(g\):

  \begin{equation*}
    \lstinline|def g(n, x)  = if n <=  2 then (x, x)  else (x, g(n - 1, x))|
  \end{equation*}

  \begin{enumerate}
    \item Evaluate \(g(3, 1)\) and \(g(4, 2)\) using the definition of \(g\).
      Suggest a type for the function \(g\) based on your observations.
    \item Label and assign type variables to the definition parameters, body,
      and its subterms.
    \item Generate the constraints on the type variables, assuming the
      definition of \(g\) is well-typed.
    \item Attempt to solve the generated constraints via unification. Argue how
    the result correlates to your observations from evaluating \(g\).
  \end{enumerate}
  
  \begin{solution}
    \begin{enumerate}
      \item \lstinline|g(3, 1)| evaluates to \lstinline|(1, (1, 1))| and
      \lstinline|g(4, 2)| evaluates to \lstinline|(2, (2, (2, 2)))|. Notably,
      these two come from disjoint types. This suggests that the function \(g\)
      is not well-typed.
      \item We can label the parameters, subterms, and assign a type to the
      function:
      \setcounter{equation}{0}
      \begin{gather}
        \lstinline|g|: \tau \\
        \lstinline|n|: \tau_n \\
        \lstinline|x|: \tau_x \\
        body: \tau_1 = \lstinline|if n <=  2 then (x, x)  else (x, g(n - 1, x))| \\
        t_1: \tau_2 = \lstinline|n <=  2| \\
        t_2: \tau_3 = \lstinline|(x, x)| \\
        t_3: \tau_4 = \lstinline|(x, g(n - 1, x))| \\
        t_4: \tau_5 = \lstinline|g(n - 1, x)| \\
        t_5: \tau_6 = \lstinline|n - 1|
      \end{gather}
      \item We can generate the constraints by looking at the top-level of each
      subterm equation:
      \begin{gather*}
        \tau = \tau_n ~\ato~ \tau_x ~\ato~ \tau_1 \tag{1, def} \\
        \tau_1 = \tau_3 \tag{4} \\
        \tau_1 = \tau_4 \tag{4} \\
        \tau_2 = \abool \tag{4} \\
        \tau_n = \aint \tag{5} \\
        \tau_3 = (\tau_x, \tau_x) \tag{6} \\
        \tau_4 = (\tau_x, \tau_5) \tag{6} \\
        \tau_5 = \tau_1 \tag{7, def} \\
        \tau_6 = \aint \tag{9}
      \end{gather*}
      \item The constraints can be solved (eliminating \(\tau_4, \tau_5\)) to
      reach a set of constraints containing the recursive constraint \(\tau_1 =
      (\tau_x, \tau_1)\). There is no type \(\tau_1\) (the output type of
      \lstinline|g|!) satisfying this. 

      This matches our previous observation where \lstinline|g| produced two
      different sized tuples as its output. 
    \end{enumerate}
  \end{solution}
  
\end{exercise}