\( % Latex Preamble definitions here (mostly usepackage) \usepackage% %[dvipsnames] {xcolor} % make sure this is before the loading font packages \newcommand\hmmax{0} \newcommand\bmmax{0} \usepackage{amssymb} \usepackage{amsmath} \usepackage{mathtools} \usepackage %[dvipsnames] {graphicx} \usepackage{float} %\usepackage[numbers]{natbib} \usepackage[document]{ragged2e} % % enumitem doesn't seem to work with beamer %\usepackage[inline]{enumitem} \usepackage{wrapfig} \usepackage{stackrel} % extensible arrows \usepackage{extpfeil} % \usepackage{trfrac} \usepackage{amsthm} \usepackage{tikz} \usepackage{tikz-cd} \usepackage{tikz} \usepackage{tikz-qtree} \usetikzlibrary{automata, positioning, arrows, shapes.geometric} \usepackage{turnstile} \usepackage{comment} %https://tex.stackexchange.com/questions/21334/is-there-a-package-that-has-the-clockwise-gapped-circle-arrow-in-it % \usepackage{mathbx} \usepackage{datetime} \usepackage{datetime2} %% Also See %% http://u.cs.biu.ac.il/~tsaban/Pdf/LaTeXCommonErrs.pdf %% for general tips \usepackage{listings} \usepackage{subfigure} \usepackage{bm} \usepackage{amsfonts} %% - also included by amssymb \usepackage{mathpazo} %% - because the OP uses mathpazo, optional %\usepackage{tufte-latex} \usepackage{comment} \usepackage{mathtools} \usepackage{bussproofs} \usepackage{hyperref} %\usepackage{cleveref} \)
\( %% Your math definitions here % \newcommand{\alphaequiv}{{\underset{\raise 0.7em\alpha}{=}}} \newcommand{\yields}{\Rightarrow} \newcommand{\derives}{\overset{*}{\yields}} \newcommand{\alphaequiv}{=_{\alpha}} \newcommand{\tto}[2]{{\overset{#1}{\underset{#2}{\longrightarrow}}}} \newcommand{\transitsto}[2]{{\overset{#1}{\underset{#2}{\longrightarrow}}}} \newcommand{\xtransitsto}[2]{{\underset{#2}{\xrightarrow{#1}}}} \newcommand{\xtransitsfrom}[2]{{\underset{#2}{\xleftarrow{#1}}}} \newcommand{\xto}[2]{{\xtransitsto{#1}{#2}}} \newcommand{\xfrom}[2]{{\xtransitsfrom{#1}{#2}}} \newcommand{\xreaches}[2]{{\underset{#2}{\xtwoheadrightarrow{#1}}}} \newcommand{\reaches}[2]{{\underset{#2}{\xtwoheadrightarrow{#1}}}} %\newcommand{\reaches}[2]{{\overset{#1}{\underset{#2}{\twoheadrightarrow}}}} %\newcommand{\goesto}[2]{\transitsto{#1}{#2}} %\newcommand{\betareducesto}{{\underset{\beta}{\rightarrow}}} \newcommand{\betareducesto}{\rightarrow_{\beta}} %\newcommand{\etareducesto}{{\underset{\eta}{\rightarrow}}} \newcommand{\etareducesto}{\rightarrow_{\eta}} %\newcommand{\betaetareducesto}{{\underset{\beta\ \eta}{\rightarrow}}} \newcommand{\betaetareducesto}{\rightarrow_{\beta\eta}} \newcommand{\preducesto}{\rhd} \newcommand{\psimplifiesto}{\stackrel{\scriptstyle{*}}{\rhd}} \newcommand{\lreducesto}{\rightsquigarrow} \newcommand{\lsimplifiesto}{\stackrel{\scriptstyle{*}}{\lreducesto}} \newcommand{\rewritesto}{\hookrightarrow} \newcommand{\goesto}[1]{\stackrel{#1}{\rightarrow}} \newcommand{\xgoesto}[1]{\xrightarrow{#1}} \newcommand{\reducesto}{\stackrel{}{\rightarrow}} \newcommand{\simplifiesto}{\stackrel{\scriptstyle{*}}{\rightarrow}} \newcommand{\connected}[1]{\stackrel{#1}{\leftrightarrow}} \newcommand{\joins}{\downarrow} \newcommand{\evaluatesto}{\Longrightarrow} %\newcommand{\lit}[1]{\hbox{\sf{#1}}} \newcommand{\lit}[1]{{\sf{#1}}} \newcommand{\true}{\lit{true}} \newcommand{\false}{\lit{false}} \def\Z{\mbox{${\mathbb Z}$}} \def\N{\mbox{${\mathbb N}$}} \def\P{\mbox{${\mathbb P}$}} \def\R{\mbox{${\mathbb R}$}} \def\T{\mbox{${\mathbb T}$}} \newcommand{\Rp}{{\mathbb{R}}^+} \def\Bool{\mbox{${\mathbb B}$}} \def\Q{\mbox{${\mathbb Q}$}} \def\sA{\mbox{${\cal A}$}} \def\sB{\mbox{${\cal B}$}} \def\sC{\mbox{${\cal C}$}} \def\sD{\mbox{${\cal D}$}} \def\sF{\mbox{${\cal F}$}} \def\sG{\mbox{${\cal G}$}} \def\sL{\mbox{${\cal L}$}} \def\sP{\mbox{${\cal P}$}} \def\sM{\mbox{${\cal M}$}} \def\sN{\mbox{${\cal N}$}} \def\sR{\mbox{${\cal R}$}} \def\sS{\mbox{${\cal S}$}} \def\sO{\mbox{${\cal O}$}} \def\sT{\mbox{${\cal T}$}} \def\sU{\mbox{${\cal U}$}} \def\th{\mbox{$\widetilde{h}$}} \def\tg{\mbox{$\widetilde{g}$}} \def\tP{\mbox{$\widetilde{P}$}} \def\norm{\mbox{$\parallel$}} \def\osum{${{\bigcirc}}\!\!\!\!{\rm s}~$} \def\pf{\noindent {\bf Proof}~~} \def\exec{\mathit{exec}} \def\Act{\mathit{A\!ct}} \def\Traces{\mathit{Traces}} \def\Spec{\mathit{Spec}} \def\uns{\mathit{unless}} \def\ens{\mathit{ensures}} \def\lto{\mathit{leads\!\!-\!\!to}} \def\a{\alpha} \def\b{\beta} \def\c{\gamma} \def\d{\delta} \def\sP{\mbox{${\cal P}$}} \def\sM{\mbox{${\cal M}$}} \def\sA{\mbox{${\cal A}$}} \def\sB{\mbox{${\cal B}$}} \def\sC{\mbox{${\cal C}$}} \def\sI{\mbox{${\cal I}$}} \def\sS{\mbox{${\cal S}$}} \def\sD{\mbox{${\cal D}$}} \def\sF{\mbox{${\cal F}$}} \def\sG{\mbox{${\cal G}$}} \def\sR{\mbox{${\cal R}$}} \def\tg{\mbox{$\widetilde{g}$}} \def\ta{\mbox{$\widetilde{a}$}} \def\tb{\mbox{$\widetilde{b}$}} \def\tc{\mbox{$\widetilde{c}$}} \def\tx{\mbox{$\widetilde{x}$}} \def\ty{\mbox{$\widetilde{y}$}} \def\tz{\mbox{$\widetilde{z}$}} \def\tI{\mbox{$\widetilde{I}$}} \def\norm{\mbox{$\parallel$}} \def\sL{\mbox{${\cal L}$}} \def\sM{\mbox{${\cal M}$}} \def\sN{\mbox{${\cal N}$}} \def\th{\mbox{$\widetilde{h}$}} \def\tg{\mbox{$\widetilde{g}$}} \def\tP{\mbox{$\widetilde{P}$}} \def\norm{\mbox{$\parallel$}} \def\to{\rightarrow} \def\ov{\overline} \def\gets{\leftarrow} \def\too{\longrightarrow} \def\To{\Rightarrow} %\def\points{\mapsto} %\def\yields{\mapsto^{*}} \def\un{\underline} \def\vep{$\varepsilon$} \def\ep{$\epsilon$} \def\tri{$\bigtriangleup$} \def\Fi{$F^{\infty}$} \def\Di{\Delta^{\infty}} \def\ebox\Box \def\emp{\emptyset} \def\leadsto{\rightharpoondown^{*}} \newcommand{\benum}{\begin{enumerate}} \newcommand{\eenum}{\end{enumerate}} \newcommand{\bdes}{\begin{description}} \newcommand{\edes}{\end{description}} \newcommand{\bt}{\begin{theorem}} \newcommand{\et}{\end{theorem}} \newcommand{\bl}{\begin{lemma}} \newcommand{\el}{\end{lemma}} % \newcommand{\bp}{\begin{prop}} % \newcommand{\ep}{\end{prop}} \newcommand{\bd}{\begin{defn}} \newcommand{\ed}{\end{defn}} \newcommand{\brem}{\begin{remark}} \newcommand{\erem}{\end{remark}} \newcommand{\bxr}{\begin{exercise}} \newcommand{\exr}{\end{exercise}} \newcommand{\bxm}{\begin{example}} \newcommand{\exm}{\end{example}} \newcommand{\beqa}{\begin{eqnarray*}} \newcommand{\eeqa}{\end{eqnarray*}} \newcommand{\bc}{\begin{center}} \newcommand{\ec}{\end{center}} \newcommand{\bcent}{\begin{center}} \newcommand{\ecent}{\end{center}} % \newcommand{\la}{\langle} % \newcommand{\ra}{\rangle} \newcommand{\bcor}{\begin{corollary}} \newcommand{\ecor}{\end{corollary}} \newcommand{\bds}{\begin{defns}} \newcommand{\eds}{\end{defns}} \newcommand{\brems}{\begin{remarks}} \newcommand{\erems}{\end{remarks}} \newcommand{\bxrs}{\begin{exercises}} \newcommand{\exrs}{\end{exercises}} \newcommand{\bxms}{\begin{examples}} \newcommand{\exms}{\end{examples}} \newcommand{\bfig}{\begin{figure}} \newcommand{\efig}{\end{figure}} \newcommand{\set}[1]{\{#1\}} \newcommand{\pair}[1]{\langle #1\rangle} \newcommand{\tuple}[1]{\langle #1\rangle} \newcommand{\size}[1]{| #1 |} \newcommand{\union}{\cup} \newcommand{\Union}{\bigcup} \newcommand{\intersection}{\cap} \newcommand{\Intersection}{\bigcap} \newcommand{\B}{\textbf{B}} %\newcommand{\be}[2]{\begin{equation} \label{#1} \tag{#2} \end{equation}} \newcommand{\abs}[1]{{\lvert}#1{\rvert}} \newcommand{\id}[1]{\mathit{#1}} \newcommand{\pfun}{\rightharpoonup} \newcommand{\ra}[1]{\kern-1.5ex\xrightarrow{\ \ #1\ \ }\phantom{}\kern-1.5ex} \newcommand{\ras}[1]{\kern-1.5ex\xrightarrow{\ \ \smash{#1}\ \ }\phantom{}\kern-1.5ex} \newcommand{\da}[1]{\bigg\downarrow\raise.5ex\rlap{\scriptstyle#1}} \newcommand{\ua}[1]{\bigg\uparrow\raise.5ex\rlap{\scriptstyle#1}} % \newcommand{\lift}[1]{#1_{\bot}} \newcommand{\signal}[1]{\tilde{#1}} \newcommand{\ida}{\stackrel{{\sf def}}{=}} \newcommand{\eqn}{\doteq} \newcommand{\deduce}[1]{\sststile{#1}{}} %% These don't sit very well with MathJax %% so we don't plan to use theorem like environments %% in org documents. %% instead we plan to use headings with %% 1. property drawers with a CLASS property identifying %% the environment %% 2. A tag with the same name as the CLASS property %% In LaTeX export, these turn into (sub)sections. %% See http://u.cs.biu.ac.il/~tsaban/Pdf/LaTeXCommonErrs.pdf %% \newtheorem{prop}[thm]{Proposition} %% \theoremstyle{plain}%default %% \newtheorem{theorem}{Theorem}[section] %% \newtheorem{lemma}{Lemma}[section] %% \newtheorem{corollary}{Corollary}[section] %% \newtheorem{definition}{Definition}[section] %% \newtheorem{remark}{Remark}[section] %% \newtheorem{example}{Example}[section] %% \newtheorem{exercise}{Exercise}[section] \newcommand{\less}[1]{#1_{<}} \newcommand{\pfn}{\rightharpoonup} \newcommand{\ffn}{\stackrel{{\sf fin}}{\rightharpoonup}} \newcommand{\stkout}[1]{\ifmmode\text{\sout{\ensuremath{#1}}}\else\sout{#1}\fi} % Caution: Not supported by MathJax! % ---------------------------------- % \DeclareMathSymbol{\shortminus}{\mathbin}{AMSa}{"39} % \usepackage{amsfonts} %% <- also included by amssymb % \DeclareMathSymbol{\shortminus}{\mathbin}{AMSa}{"39} \usepackage{mathpazo} %% <- because the OP uses mathpazo, optional \newcommand{\mbf}[1]{\mathbf{#1}} \newcommand{\floor}[1]{\left\lfloor #1 \right\rfloor} \newcommand{\ceil}[1]{\left\lceil #1 \right\rceil} \newcommand{\rel}{\twoheadrightarrow} \newcommand{\map}{\rightarrow} %\newcommand{\fixed}{\boldsymbol{\circlearrowleft}} \newcommand{\terminal}{\not\xto{}{}} \newcommand{\fixed}{\bm\circlearrowleft} \newcommand{\imp}{\rightarrow} \newcommand{\dimp}{\leftrightarrow} % double implication \newcommand{\lequiv}{\Longleftrightarrow} % logical equivalence \newcommand{\limplies}{\Rightarrow} \newcommand{\lxor}{\veebar} \)
UP | HOME

Representations of Continuations: An exploration using Factorial

Table of Contents

1 Revision History

[2022-11-05 Sat]
Created.

2 Introduction

The purpose of this note is to explore different representations of continuations. To illustrate the transformations, we use as an example, the factorial function.

We start with the factorial written in direct style using recursion. Then we transform it to CPS. Then we abstract the representation and application of continuations. They are still procedures but only apply-k and the continuation constructors know this. Next, continuations are turned from procedures to data (records). As an alternative, continuations are represented as records containing closures and other continuations.

3 Direct Style

;;; fact: nat? -> nat?
(define fact
  (lambda (n)
    (if (zero? n)
	1
	(* n (fact (sub1 n))))))

4 CPS with continuations as procedures

4.1 Factorial in CPS

A value-continuation takes a expressible value (natural number here). We write a continuation that receives a value of type T as (k T). Since continuations don't return a value, we can think of the type (k T) as the `return only to top-level function' T->ans? where ans? has the effect of printing a value on the screen and returning that value to the top level.

A more precise way to think about effects (like I/O to a stream) is using Monads, but we won't be doing that in this course.

;;; factorial with continuations:
;;; fact/k : [nat? (k nat?)] -> ans?
(define fact/k
  (lambda (n k)
    (if
      (zero? n)
      (k 1)
      (fact/k (sub1 n)
	(lambda (v)
	  (k (* n v)))))))

4.2 Top-level continuation

top-k simply prints the answer, but returns the value (at the top-level). The return value is used only print the final value or feed it to a test case.

;;; top-k : (k nat?)
(define top-k
  (lambda (v)
    (printf "CPS: ans=~a~n" v)
    v))

4.3 Factorial top-level interface

Interface to factorial.

;;; nat? -> nat?
(define fact
  (lambda (n)
    (fact/k n top-k)))

5 Representation independence

Note that fact/k assumes continuations are procedures. This version introduces explicit operations to construct and apply a continuation. This isolates any assumptions about representation to these functions.

5.1 Continuation Constructors

From now on, we will use the notation k? to mean (k nat?). top-k constructs the top-level continuation. fact1-k takes a natural and a continuation and constructs a new continuation.

;;; top-k: [] -> k?
(define top-k
  (lambda ()
    (lambda (v)
      (printf "REP-IND: ans=~a~n" v)
      v)))

;;; fact1-k : [nat? k?] -> k?
(define fact1-k
  (lambda (n k)
    (lambda (v)
      (apply-k k (* n v)))))

Note that a continuation maker abstracts out as its formals, the free identifiers in the body of the continuation being constructed. For instance, fact1-k has as its formals, n and k, which are the free identifiers in the body of the continuation being returned.

5.2 Applying the continuation

Since a continuation is a function, apply-k simply applies its argument k to the value v.

;;; continuation application
;;; apply-k : [k?  nat?] -> ans?
(define apply-k
  (lambda (k v)
    (k v)))

5.3 Factorial fact/k with representation independence

Note the use of apply-k and make-fact1-k. These functions help in abstracting the representation of continuations. Looking at fact/k, there is no need to assume that fact-k relies on k being a procedure.

;;; fact/k : [nat? k?] -> ans?
(define fact/k
  (lambda (n k)
    (if
      (zero? n)
      (apply-k k 1)
      (fact/k (sub1 n)
	(fact1-k n k)))))

5.4 Top-level factorial interface

;;; fact : nat? -> nat?
(define fact
  (lambda (n)
    (fact/k n (top-k))))

6 Record representation

Continuations are now represented as data, or more accurately, records.

6.1 Continuation makers

The continuation makers simply gather the free identifiers in a continuation and tag them.

(define-datatype k k?
  [top-k]
  [fact1-k (val nat?) (saved-k k?)])

6.2 Applying the continuation

apply-k does the heavy lifting by taking actions based on the continuation type. Applying a continuation k of type fact-1-k to a value v entails the following: extract the saved continuation saved-k and a value val from k and then apply saved-k to (* val v). So the multiplications happen at the time of invoking apply-k. Since apply-k (and in fact all the procedures) are invoked as tail calls, the second formal to apply-k effectively performs the role of an accumulator. This becomes evident when we define a traceable version of apply-k.

(trace-define apply-k
  (lambda (c v)
    (cases k c
      [top-k () 
	(printf "DATA-REP: ans=~a~n" v) v]
      [fact1-k (val saved-k)
	(apply-k saved-k (* val v))])))

6.3 fact/k and fact

There are no changes to these functions. We are cashing in on the investment into abstraction.

7 Closure representation

Each continuation (except the top one) is now seen as a record consisting of a closure followed by a continuation.

7.1 Continuation are records that contain closures

The clo-k constructor takes a closure and a continuation and returns a new continuation.

(define-datatype k k?
  [top-k]
  [clo-k (clo procedure?) (k k?)])

7.2 Applying the continuations: apply-k

The behaviour of apply-k is the same as earlier for top-k. When holding a continuation of type clo-k, it extracts the closure into clo and the continuation into k. Then apply-k simply runs the closure on v and tail-recursively invokes apply-k.

(define apply-k
  (lambda (c v)
    (cases k c
      [top-k () 
	     (printf "CC: ans=~a~n" v) 
	     v]
      [clo-k (clo k)
	     (apply-k k
		      (clo v) ; this is a simple computation
		      ; whose result is passed to the waiting
		      ; continuation k
		      )])))

Note that apply-k is quite generic: all factorial specific computation is abstracted away into the the closure clo.

7.3 fact/k

(define fact/k
  (lambda (n k)
    (if (zero? n)
	(apply-k k 1) 
	(fact/k (- n 1)
		(clo-k
		 (lambda (v) (* n v))
		 k)))))

Note that the continuation constructed by clo-k employs a closure whose operations are all simple. clo-k separates the `simple' closure from the waiting continuation k. Contrast this with the continuation in the CPS version:

(lambda (v)
  (k (* n v)))

8 Conclusion

We have seen five different versions of the factorial program. the first is direct style factorial. The CPS style uses continuations as procedures. This representation is abstrated next. Finally continuations are turned into tagged data: as records containing primitive data (natural number), and alteratively as records containing closures. These closures encapsulate simple computations.

Further transformations like transformation to imperative form, register-transformation and the stepper transformation may be done. These are left as exercises.

Author: choppell

Created: 2023-11-25 Sat 09:15

Validate