Ver Fonte

copy edits to ch 10

Jeremy Siek há 3 anos atrás
pai
commit
d93081a2e3
1 ficheiros alterados com 146 adições e 144 exclusões
  1. 146 144
      book.tex

+ 146 - 144
book.tex

@@ -46,7 +46,7 @@
 \lstset{%
 \lstset{%
 language=Lisp,
 language=Lisp,
 basicstyle=\ttfamily\small,
 basicstyle=\ttfamily\small,
-morekeywords={seq,assign,program,block,define,lambda,match,goto,if,else,then,struct,Integer,Boolean,Vector,Void,Any,while,begin,define,public,override,class},
+morekeywords={lambda,match,goto,if,else,then,struct,Integer,Boolean,Vector,Void,Any,while,begin,define,public,override,class},
 deletekeywords={read,mapping,vector},
 deletekeywords={read,mapping,vector},
 escapechar=|,
 escapechar=|,
 columns=flexible,
 columns=flexible,
@@ -18882,7 +18882,7 @@ completion without error.
      {\ttfamily\footnotesize convert\_to\_closures} (F1-2);
      {\ttfamily\footnotesize convert\_to\_closures} (F1-2);
 \path[->,bend right=15] (F1-2) edge [right] node
 \path[->,bend right=15] (F1-2) edge [right] node
      {\ttfamily\footnotesize limit\_functions} (F1-3);
      {\ttfamily\footnotesize limit\_functions} (F1-3);
-\path[->,bend right=15] (F1-3) edge [below] node
+\path[->,bend right=15] (F1-3) edge [left] node
      {\ttfamily\footnotesize expose\_allocation} (F1-4);
      {\ttfamily\footnotesize expose\_allocation} (F1-4);
 \path[->,bend right=15] (F1-4) edge [below] node
 \path[->,bend right=15] (F1-4) edge [below] node
      {\ttfamily\footnotesize uncover\_get!} (F1-5);
      {\ttfamily\footnotesize uncover\_get!} (F1-5);
@@ -18933,26 +18933,26 @@ for the compilation of \LangDyn{}.
 \index{subject}{gradual typing}
 \index{subject}{gradual typing}
 \setcounter{footnote}{0}
 \setcounter{footnote}{0}
 
 
-This chapter studies a language, \LangGrad{}, in which the programmer
+This chapter studies the language \LangGrad{}, in which the programmer
 can choose between static and dynamic type checking in different parts
 can choose between static and dynamic type checking in different parts
 of a program, thereby mixing the statically typed \LangLam{} language
 of a program, thereby mixing the statically typed \LangLam{} language
 with the dynamically typed \LangDyn{}. There are several approaches to
 with the dynamically typed \LangDyn{}. There are several approaches to
-mixing static and dynamic typing, including multi-language
+mixing static and dynamic typing, including multilanguage
 integration~\citep{Tobin-Hochstadt:2006fk,Matthews:2007zr} and hybrid
 integration~\citep{Tobin-Hochstadt:2006fk,Matthews:2007zr} and hybrid
 type checking~\citep{Flanagan:2006mn,Gronski:2006uq}. In this chapter
 type checking~\citep{Flanagan:2006mn,Gronski:2006uq}. In this chapter
 we focus on \emph{gradual typing}\index{subject}{gradual typing}, in which the
 we focus on \emph{gradual typing}\index{subject}{gradual typing}, in which the
 programmer controls the amount of static versus dynamic checking by
 programmer controls the amount of static versus dynamic checking by
 adding or removing type annotations on parameters and
 adding or removing type annotations on parameters and
 variables~\citep{Anderson:2002kd,Siek:2006bh}.
 variables~\citep{Anderson:2002kd,Siek:2006bh}.
-%
-The concrete syntax of \LangGrad{} is defined in
-figure~\ref{fig:Lgrad-concrete-syntax} and its abstract syntax is
-defined in figure~\ref{fig:Lgrad-syntax}. The main syntactic
-difference between \LangLam{} and \LangGrad{} is that type annotations
-are optional, which is specified in the grammar using the \Param{} and
-\itm{ret} nonterminals. In the abstract syntax, type annotations are
-not optional but we use the \CANYTY{} type when a type annotation is
-absent.
+
+The definition of the concrete syntax of \LangGrad{} is shown in
+figure~\ref{fig:Lgrad-concrete-syntax} and the definnintion of its
+abstract syntax is shown in figure~\ref{fig:Lgrad-syntax}. The main
+syntactic difference between \LangLam{} and \LangGrad{} is that type
+annotations are optional, which is specified in the grammar using the
+\Param{} and \itm{ret} nonterminals. In the abstract syntax, type
+annotations are not optional, but we use the \CANYTY{} type when a type
+annotation is absent.
 
 
 \newcommand{\LgradGrammarRacket}{
 \newcommand{\LgradGrammarRacket}{
 \begin{array}{lcl}
 \begin{array}{lcl}
@@ -19099,7 +19099,7 @@ next two sections.
 \section{Type Checking \LangGrad{}}
 \section{Type Checking \LangGrad{}}
 \label{sec:gradual-type-check}
 \label{sec:gradual-type-check}
 
 
-We begin by discussing the type checking of a partially-typed variant
+We begin by discussing the type checking of a partially typed variant
 of the \code{map} example from chapter~\ref{ch:Lfun}, shown in
 of the \code{map} example from chapter~\ref{ch:Lfun}, shown in
 figure~\ref{fig:gradual-map}.  The \code{map} function itself is
 figure~\ref{fig:gradual-map}.  The \code{map} function itself is
 statically typed, so there is nothing special happening there with
 statically typed, so there is nothing special happening there with
@@ -19107,21 +19107,21 @@ respect to type checking. On the other hand, the \code{inc} function
 does not have type annotations, so parameter \code{x} is given the
 does not have type annotations, so parameter \code{x} is given the
 type \CANYTY{} and the return type of \code{inc} is \CANYTY{}.  Now
 type \CANYTY{} and the return type of \code{inc} is \CANYTY{}.  Now
 consider the \code{+} operator inside \code{inc}. It expects both
 consider the \code{+} operator inside \code{inc}. It expects both
-arguments to have type \INTTY{}, but its first argument \code{x}
-has type \CANYTY{}.  In a gradually typed language, such differences
-are allowed so long as the types are \emph{consistent}, that is, they
-are equal except in places where there is an \CANYTY{} type. That is,
-the type \CANYTY{} is consistent with every other type.
-Figure~\ref{fig:consistent} defines the
+arguments to have type \INTTY{}, but its first argument \code{x} has
+type \CANYTY{}.  In a gradually typed language, such differences are
+allowed so long as the types are \emph{consistent}; that is, they are
+equal except in places where there is an \CANYTY{} type. That is, the
+type \CANYTY{} is consistent with every other type.
+Figure~\ref{fig:consistent} shows the definitionn of the
 \racket{\code{consistent?}}\python{\code{consistent}} method.
 \racket{\code{consistent?}}\python{\code{consistent}} method.
 %
 %
 So the type checker allows the \code{+} operator to be applied
 So the type checker allows the \code{+} operator to be applied
 to \code{x} because \CANYTY{} is consistent with \INTTY{}.
 to \code{x} because \CANYTY{} is consistent with \INTTY{}.
 %
 %
-Next consider the call to the \code{map} function in
+Next consider the call to the \code{map} function shown in
 figure~\ref{fig:gradual-map} with the arguments \code{inc} and a
 figure~\ref{fig:gradual-map} with the arguments \code{inc} and a
 tuple. The \code{inc} function has type
 tuple. The \code{inc} function has type
-\racket{\code{(Any -> Any)}}\python{\code{Callable[[Any],Any]}}
+\racket{\code{(Any -> Any)}}\python{\code{Callable[[Any],Any]}},
 but parameter \code{f} of \code{map} has type
 but parameter \code{f} of \code{map} has type
 \racket{\code{(Integer -> Integer)}}\python{\code{Callable[[int],int]}}.
 \racket{\code{(Integer -> Integer)}}\python{\code{Callable[[int],int]}}.
 The type checker for \LangGrad{} accepts this call because the two types are
 The type checker for \LangGrad{} accepts this call because the two types are
@@ -19156,7 +19156,7 @@ print(t[1])
   \fi}
   \fi}
   \end{tcolorbox}
   \end{tcolorbox}
 
 
-  \caption{A partially-typed version of the \code{map} example.}
+  \caption{A partially typed version of the \code{map} example.}
 \label{fig:gradual-map}
 \label{fig:gradual-map}
 \end{figure}
 \end{figure}
 
 
@@ -19207,14 +19207,14 @@ error, such as applying \code{map} to a function that sometimes
 returns a Boolean, as shown in figure~\ref{fig:map-maybe_inc}.  The
 returns a Boolean, as shown in figure~\ref{fig:map-maybe_inc}.  The
 type checker for \LangGrad{} accepts this program because the type of
 type checker for \LangGrad{} accepts this program because the type of
 \code{maybe\_inc} is consistent with the type of parameter \code{f} of
 \code{maybe\_inc} is consistent with the type of parameter \code{f} of
-\code{map}, that is,
+\code{map}; that is,
 \racket{\code{(Any -> Any)}}\python{\code{Callable[[Any],Any]}}
 \racket{\code{(Any -> Any)}}\python{\code{Callable[[Any],Any]}}
 is consistent with
 is consistent with
 \racket{\code{(Integer -> Integer)}}\python{\code{Callable[[int],int]}}.
 \racket{\code{(Integer -> Integer)}}\python{\code{Callable[[int],int]}}.
 One might say that a gradual type checker is optimistic in that it
 One might say that a gradual type checker is optimistic in that it
 accepts programs that might execute without a runtime type error.
 accepts programs that might execute without a runtime type error.
 %
 %
-The type checker for \LangGrad{} is defined in
+The definition of the type checker for \LangGrad{} is shown in
 figures~\ref{fig:type-check-Lgradual-1}, \ref{fig:type-check-Lgradual-2},
 figures~\ref{fig:type-check-Lgradual-1}, \ref{fig:type-check-Lgradual-2},
 and \ref{fig:type-check-Lgradual-3}.
 and \ref{fig:type-check-Lgradual-3}.
 
 
@@ -19285,13 +19285,13 @@ Here we give a preview of how the runtime checking is accomplished;
 the following sections provide the details.
 the following sections provide the details.
 
 
 The runtime checking is carried out by a new \code{Cast} AST node that
 The runtime checking is carried out by a new \code{Cast} AST node that
-is generate in a new pass named \code{cast\_insert}.  The output of
+is generated in a new pass named \code{cast\_insert}.  The output of
 \code{cast\_insert} is a program in the \LangCast{} language, which
 \code{cast\_insert} is a program in the \LangCast{} language, which
 simply adds \code{Cast} and \CANYTY{} to \LangLam{}.
 simply adds \code{Cast} and \CANYTY{} to \LangLam{}.
 %
 %
 Figure~\ref{fig:map-cast} shows the output of \code{cast\_insert} for
 Figure~\ref{fig:map-cast} shows the output of \code{cast\_insert} for
 \code{map} and \code{maybe\_inc}.  The idea is that \code{Cast} is
 \code{map} and \code{maybe\_inc}.  The idea is that \code{Cast} is
-inserted every time the type checker sees two types that are
+inserted every time the type checker encounters two types that are
 consistent but not equal. In the \code{inc} function, \code{x} is
 consistent but not equal. In the \code{inc} function, \code{x} is
 cast to \INTTY{} and the result of the \code{+} is cast to
 cast to \INTTY{} and the result of the \code{+} is cast to
 \CANYTY{}.  In the call to \code{map}, the \code{inc} argument
 \CANYTY{}.  In the call to \code{map}, the \code{inc} argument
@@ -19735,21 +19735,21 @@ cast from \INTTY{} to \CANYTY{} can be accomplished with the
 \code{Inject} operator of \LangAny{}, which puts the integer into a
 \code{Inject} operator of \LangAny{}, which puts the integer into a
 tagged value (figure~\ref{fig:interp-Lany}). Similarly, a cast from
 tagged value (figure~\ref{fig:interp-Lany}). Similarly, a cast from
 \CANYTY{} to \INTTY{} is accomplished with the \code{Project}
 \CANYTY{} to \INTTY{} is accomplished with the \code{Project}
-operator, that is, by checking the value's tag and either retrieving
+operator, by checking the value's tag and either retrieving
 the underlying integer or signalling an error if the tag is not the
 the underlying integer or signalling an error if the tag is not the
 one for integers (figure~\ref{fig:interp-Lany-aux}).
 one for integers (figure~\ref{fig:interp-Lany-aux}).
 %
 %
-Things get more interesting for casts involving function, tuple, or array
-types.
+Things get more interesting with casts involving function, tuple, or
+array types.
 
 
 Consider the cast of the function \code{maybe\_inc} from
 Consider the cast of the function \code{maybe\_inc} from
 \racket{\code{(Any -> Any)}}\python{\code{Callable[[Any], Any]}}
 \racket{\code{(Any -> Any)}}\python{\code{Callable[[Any], Any]}}
 to
 to
 \racket{\code{(Integer -> Integer)}}\python{\code{Callable[[int], int]}}
 \racket{\code{(Integer -> Integer)}}\python{\code{Callable[[int], int]}}
-in figure~\ref{fig:map-maybe_inc}.
+shown in figure~\ref{fig:map-maybe_inc}.
 When the \code{maybe\_inc} function flows through
 When the \code{maybe\_inc} function flows through
 this cast at runtime, we don't know whether it will return
 this cast at runtime, we don't know whether it will return
-an integer, as that depends on the input from the user.
+an integer, because that depends on the input from the user.
 The \LangCast{} interpreter therefore delays the checking
 The \LangCast{} interpreter therefore delays the checking
 of the cast until the function is applied. To do so it
 of the cast until the function is applied. To do so it
 wraps \code{maybe\_inc} in a new function that casts its parameter
 wraps \code{maybe\_inc} in a new function that casts its parameter
@@ -19765,20 +19765,18 @@ the challenge assignment of section~\ref{sec:arrays}.
 %
 %
 \fi}
 \fi}
 %
 %
-Consider the example in figure~\ref{fig:map-bang} that
-defines a partially-typed version of \code{map} whose parameter
+Consider the example presented in figure~\ref{fig:map-bang} that
+defines a partially typed version of \code{map} whose parameter
 \code{v} has type
 \code{v} has type
 \racket{\code{(Vector Any Any)}}\python{\code{list[Any]}}
 \racket{\code{(Vector Any Any)}}\python{\code{list[Any]}}
 and that updates \code{v} in place
 and that updates \code{v} in place
-instead of returning a new tuple. So we name this function
+instead of returning a new tuple. So, we name this function
 \code{map\_inplace}. We apply \code{map\_inplace} to an
 \code{map\_inplace}. We apply \code{map\_inplace} to an
 \racket{tuple}\python{array} of integers, so the type checker inserts a
 \racket{tuple}\python{array} of integers, so the type checker inserts a
 cast from
 cast from
-\racket{\code{(Vector Integer Integer)}}
-\python{\code{list[int]}}
+\racket{\code{(Vector Integer Integer)}}\python{\code{list[int]}}
 to
 to
-\racket{\code{(Vector Any Any)}}
-\python{\code{list[Any]}}.
+\racket{\code{(Vector Any Any)}}\python{\code{list[Any]}}.
 A naive way for the \LangCast{} interpreter to cast between
 A naive way for the \LangCast{} interpreter to cast between
 \racket{tuple}\python{array} types would be a build a new
 \racket{tuple}\python{array} types would be a build a new
 \racket{tuple}\python{array}
 \racket{tuple}\python{array}
@@ -19787,7 +19785,7 @@ of casting each of the original elements to the appropriate target
 type.
 type.
 However, this approach is not valid for mutable data structures.
 However, this approach is not valid for mutable data structures.
 In the example of figure~\ref{fig:map-bang},
 In the example of figure~\ref{fig:map-bang},
-if the cast created a new \racket{tuple}\python{array}, then the updates inside of
+if the cast created a new \racket{tuple}\python{array}, then the updates inside
 \code{map\_inplace} would happen to the new \racket{tuple}\python{array} and not
 \code{map\_inplace} would happen to the new \racket{tuple}\python{array} and not
 the original one.
 the original one.
 
 
@@ -19849,18 +19847,18 @@ from \CANYTY{} to \INTTY{}.
   the proxy casts the tagged value from \CANYTY{} to \INTTY{}.
   the proxy casts the tagged value from \CANYTY{} to \INTTY{}.
 }
 }
 
 
-The final category of cast that we need to consider are casts between
-the \CANYTY{} type and higher-order types such as functions or
+The final category of cast that we need to consider consist of casts between
+the \CANYTY{} type and higher-order types such as functions and
 \racket{tuples}\python{lists}. Figure~\ref{fig:map-any} shows a
 \racket{tuples}\python{lists}. Figure~\ref{fig:map-any} shows a
 variant of \code{map\_inplace} in which parameter \code{v} does not
 variant of \code{map\_inplace} in which parameter \code{v} does not
 have a type annotation, so it is given type \CANYTY{}. In the call to
 have a type annotation, so it is given type \CANYTY{}. In the call to
 \code{map\_inplace}, the \racket{tuple}\python{list} has type
 \code{map\_inplace}, the \racket{tuple}\python{list} has type
-\racket{\code{(Vector Integer Integer)}}\python{\code{list[int]}}
+\racket{\code{(Vector Integer Integer)}}\python{\code{list[int]}},
 so the type checker inserts a cast to \CANYTY{}. A first thought is to use
 so the type checker inserts a cast to \CANYTY{}. A first thought is to use
 \code{Inject}, but that doesn't work because
 \code{Inject}, but that doesn't work because
 \racket{\code{(Vector Integer Integer)}}\python{\code{list[int]}} is not
 \racket{\code{(Vector Integer Integer)}}\python{\code{list[int]}} is not
 a flat type. Instead, we must first cast to
 a flat type. Instead, we must first cast to
-\racket{\code{(Vector Any Any)}}\python{\code{list[Any]}} (which is flat)
+\racket{\code{(Vector Any Any)}}\python{\code{list[Any]}}, which is flat,
 and then inject to \CANYTY{}.
 and then inject to \CANYTY{}.
 
 
 \begin{figure}[tbp]
 \begin{figure}[tbp]
@@ -20016,14 +20014,14 @@ print( v[1] )
 The \LangCast{} interpreter uses an auxiliary function named
 The \LangCast{} interpreter uses an auxiliary function named
 \code{apply\_cast} to cast a value from a source type to a target type,
 \code{apply\_cast} to cast a value from a source type to a target type,
 shown in figure~\ref{fig:apply_cast}. You'll find that it handles all
 shown in figure~\ref{fig:apply_cast}. You'll find that it handles all
-of the kinds of casts that we've discussed in this section.
+the kinds of casts that we've discussed in this section.
 %
 %
-The interpreter for \LangCast{} is defined in
+The definition of the interpreter for \LangCast{} is shown in
 figure~\ref{fig:interp-Lcast}, with the case for \code{Cast}
 figure~\ref{fig:interp-Lcast}, with the case for \code{Cast}
 dispatching to \code{apply\_cast}.
 dispatching to \code{apply\_cast}.
 \racket{To handle the addition of tuple
 \racket{To handle the addition of tuple
 proxies, we update the tuple primitives in \code{interp-op} using the
 proxies, we update the tuple primitives in \code{interp-op} using the
-functions in figure~\ref{fig:guarded-tuple}.}
+functions given in figure~\ref{fig:guarded-tuple}.}
 Next we turn to the individual passes needed for compiling \LangGrad{}.
 Next we turn to the individual passes needed for compiling \LangGrad{}.
 
 
 
 
@@ -20196,21 +20194,21 @@ to type \CANYTY{} (if they are not already of that type).
 \section{Lower Casts}
 \section{Lower Casts}
 \label{sec:lower_casts}
 \label{sec:lower_casts}
 
 
-The next step in the journey towards x86 is the \code{lower\_casts}
+The next step in the journey toward x86 is the \code{lower\_casts}
 pass that translates the casts in \LangCast{} to the lower-level
 pass that translates the casts in \LangCast{} to the lower-level
 \code{Inject} and \code{Project} operators and new operators for
 \code{Inject} and \code{Project} operators and new operators for
 proxies, extending the \LangLam{} language to \LangProxy{}.
 proxies, extending the \LangLam{} language to \LangProxy{}.
 The \LangProxy{} language can also be described as an extension of
 The \LangProxy{} language can also be described as an extension of
 \LangAny{}, with the addition of proxies. We recommend creating an
 \LangAny{}, with the addition of proxies. We recommend creating an
 auxiliary function named \code{lower\_cast} that takes an expression
 auxiliary function named \code{lower\_cast} that takes an expression
-(in \LangCast{}), a source type, and a target type, and translates it
-to expression in \LangProxy{}.
+(in \LangCast{}), a source type, and a target type and translates it
+to an expression in \LangProxy{}.
 
 
 The \code{lower\_cast} function can follow a code structure similar to
 The \code{lower\_cast} function can follow a code structure similar to
 the \code{apply\_cast} function (figure~\ref{fig:apply_cast}) used in
 the \code{apply\_cast} function (figure~\ref{fig:apply_cast}) used in
-the interpreter for \LangCast{} because it must handle the same cases
+the interpreter for \LangCast{}, because it must handle the same cases
 as \code{apply\_cast} and it needs to mimic the behavior of
 as \code{apply\_cast} and it needs to mimic the behavior of
-\code{apply\_cast}. The most interesting cases are those concerning
+\code{apply\_cast}. The most interesting cases concern
 the casts involving tuple, array, and function types.
 the casts involving tuple, array, and function types.
 
 
 As mentioned in section~\ref{sec:interp-casts}, a cast from one array
 As mentioned in section~\ref{sec:interp-casts}, a cast from one array
@@ -20218,7 +20216,7 @@ type to another array type is accomplished by creating a proxy that
 intercepts the operations on the underlying array. Here we make the
 intercepts the operations on the underlying array. Here we make the
 creation of the proxy explicit with the
 creation of the proxy explicit with the
 \racket{\code{vectorof-proxy}}\python{\code{ListProxy}} AST node. It
 \racket{\code{vectorof-proxy}}\python{\code{ListProxy}} AST node. It
-takes fives arguments, the first is an expression for the array, the
+takes fives arguments: the first is an expression for the array, the
 second is a function for casting an element that is being read from
 second is a function for casting an element that is being read from
 the array, the third is a function for casting an element that is
 the array, the third is a function for casting an element that is
 being written to the array, the fourth is the type of the underlying
 being written to the array, the fourth is the type of the underlying
@@ -20234,15 +20232,15 @@ Because there is a separate element type for each slot in the tuple,
 we need not just one function for casting during a read, but instead a tuple
 we need not just one function for casting during a read, but instead a tuple
 of functions.
 of functions.
 %
 %
-Also, as we shall see in the next section, we need to differentiate
+Also, as we show in the next section, we need to differentiate
 these tuples from the user-created ones, so we recommend using a new
 these tuples from the user-created ones, so we recommend using a new
 AST node named \racket{\code{raw-vector}}\python{\code{RawTuple}}
 AST node named \racket{\code{raw-vector}}\python{\code{RawTuple}}
 instead of \racket{\code{vector}}\python{\code{Tuple}} to create the
 instead of \racket{\code{vector}}\python{\code{Tuple}} to create the
 tuples of functions.
 tuples of functions.
 %
 %
 Figure~\ref{fig:map-bang-lower-cast} shows the output of
 Figure~\ref{fig:map-bang-lower-cast} shows the output of
-\code{lower\_casts} on the example in figure~\ref{fig:map-bang} that
-involved casting an array of integers to an array of \CANYTY{}.
+\code{lower\_casts} on the example given in figure~\ref{fig:map-bang}
+that involved casting an array of integers to an array of \CANYTY{}.
 
 
 \begin{figure}[tbp]
 \begin{figure}[tbp]
 \begin{tcolorbox}[colback=white]  
 \begin{tcolorbox}[colback=white]  
@@ -20290,7 +20288,7 @@ def main() -> int:
 \fi}
 \fi}
 \end{tcolorbox}
 \end{tcolorbox}
 
 
-\caption{Output of \code{lower\_casts} on the example in
+\caption{Output of \code{lower\_casts} on the example shown in
   figure~\ref{fig:map-bang}.}
   figure~\ref{fig:map-bang}.}
 \label{fig:map-bang-lower-cast}
 \label{fig:map-bang-lower-cast}
 \end{figure}
 \end{figure}
@@ -20299,11 +20297,11 @@ A cast from one function type to another function type is accomplished
 by generating a \code{lambda} whose parameter and return types match
 by generating a \code{lambda} whose parameter and return types match
 the target function type. The body of the \code{lambda} should cast
 the target function type. The body of the \code{lambda} should cast
 the parameters from the target type to the source type. (Yes,
 the parameters from the target type to the source type. (Yes,
-backwards! Functions are contravariant\index{subject}{contravariant}
-in the parameters.). Afterwards, call the underlying function and then
+backward! Functions are contravariant\index{subject}{contravariant}
+in the parameters.). Afterward, call the underlying function and then
 cast the result from the source return type to the target return type.
 cast the result from the source return type to the target return type.
 Figure~\ref{fig:map-lower-cast} shows the output of the
 Figure~\ref{fig:map-lower-cast} shows the output of the
-\code{lower\_casts} pass on the \code{map} example in
+\code{lower\_casts} pass on the \code{map} example give in
 figure~\ref{fig:gradual-map}. Note that the \code{inc} argument in the
 figure~\ref{fig:gradual-map}. Note that the \code{inc} argument in the
 call to \code{map} is wrapped in a \code{lambda}.
 call to \code{map} is wrapped in a \code{lambda}.
 
 
@@ -20340,7 +20338,7 @@ def main() -> int:
 \fi}
 \fi}
 \end{tcolorbox}
 \end{tcolorbox}
 
 
-\caption{Output of \code{lower\_casts} on the example in
+\caption{Output of \code{lower\_casts} on the example shown in
   figure~\ref{fig:gradual-map}.}
   figure~\ref{fig:gradual-map}.}
 \label{fig:map-lower-cast}
 \label{fig:map-lower-cast}
 \end{figure}
 \end{figure}
@@ -20349,11 +20347,11 @@ def main() -> int:
 \section{Differentiate Proxies}
 \section{Differentiate Proxies}
 \label{sec:differentiate-proxies}
 \label{sec:differentiate-proxies}
 
 
-So far the responsibility of differentiating tuples and tuple proxies
+So far, the responsibility of differentiating tuples and tuple proxies
 has been the job of the interpreter.
 has been the job of the interpreter.
 %
 %
 \racket{For example, the interpreter for \LangCast{} implements
 \racket{For example, the interpreter for \LangCast{} implements
-  \code{vector-ref} using the \code{guarded-vector-ref} function in
+  \code{vector-ref} using the \code{guarded-vector-ref} function shown in
   figure~\ref{fig:guarded-tuple}.}
   figure~\ref{fig:guarded-tuple}.}
 %
 %
 In the \code{differentiate\_proxies} pass we shift this responsibility
 In the \code{differentiate\_proxies} pass we shift this responsibility
@@ -20378,10 +20376,10 @@ can be either arrays or array proxies.
 These new types come with a suite of new primitive operations.
 These new types come with a suite of new primitive operations.
 
 
 {\if\edition\racketEd    
 {\if\edition\racketEd    
-A tuple proxy is represented by a tuple containing three things: 1) the
-underlying tuple, 2) a tuple of functions for casting elements that
-are read from the tuple, and 3) a tuple of functions for casting
-values to be written to the tuple. So we define the following
+A tuple proxy is represented by a tuple containing three things: (1) the
+underlying tuple, (2) a tuple of functions for casting elements that
+are read from the tuple, and (3) a tuple of functions for casting
+values to be written to the tuple. So, we define the following
 abbreviation for the type of a tuple proxy:
 abbreviation for the type of a tuple proxy:
 \[
 \[
 \itm{TupleProxy} (T\ldots \Rightarrow T'\ldots)
 \itm{TupleProxy} (T\ldots \Rightarrow T'\ldots)
@@ -20541,7 +20539,9 @@ Tuple(|$e'_1, \ldots, e'_n$|)
 \end{lstlisting}
 \end{lstlisting}
 \fi}
 \fi}
 
 
-The \racket{\code{vector-proxy}}\python{\code{TupleProxy}} AST translates as follows.
+The \racket{\code{vector-proxy}}\python{\code{TupleProxy}} AST
+translates as follows:
+%
 {\if\edition\racketEd    
 {\if\edition\racketEd    
 \begin{lstlisting}
 \begin{lstlisting}
 (vector-proxy |$e_1~e_2~e_3$|)
 (vector-proxy |$e_1~e_2~e_3$|)
@@ -20589,7 +20589,7 @@ Recall that the \code{reveal\_casts} pass
 %
 %
 In particular, \code{Project} turns into a conditional expression that
 In particular, \code{Project} turns into a conditional expression that
 inspects the tag and retrieves the underlying value.  Here we need to
 inspects the tag and retrieves the underlying value.  Here we need to
-augment the translation of \code{Project} to handle the situation when
+augment the translation of \code{Project} to handle the situation in which
 the target type is \code{PVector}.  Instead of using
 the target type is \code{PVector}.  Instead of using
 \code{vector-length} we need to use \code{proxy-vector-length}.
 \code{vector-length} we need to use \code{proxy-vector-length}.
 \begin{lstlisting}
 \begin{lstlisting}
@@ -20620,18 +20620,19 @@ Otherwise, the only other changes are adding cases that copy the new AST nodes.
 The auxiliary function that translates type annotations needs to be
 The auxiliary function that translates type annotations needs to be
 updated to handle the \PTUPLETYNAME{} and \PARRAYTYNAME{} types.
 updated to handle the \PTUPLETYNAME{} and \PARRAYTYNAME{} types.
 %
 %
-Otherwise, the only other changes are adding cases that copy the new AST nodes.
+Otherwise, the only other changes are adding cases that copy the new
+AST nodes.
 
 
 \section{Select Instructions}
 \section{Select Instructions}
 \label{sec:select-instructions-gradual}
 \label{sec:select-instructions-gradual}
 
 
 Recall that the \code{select\_instructions} pass is responsible for
 Recall that the \code{select\_instructions} pass is responsible for
-lowering the primitive operations into x86 instructions.  So we need
+lowering the primitive operations into x86 instructions.  So, we need
 to translate the new operations on \PTUPLETYNAME{} and \PARRAYTYNAME{}
 to translate the new operations on \PTUPLETYNAME{} and \PARRAYTYNAME{}
 to x86.  To do so, the first question we need to answer is how to
 to x86.  To do so, the first question we need to answer is how to
 differentiate between tuple and tuples proxies, and likewise for
 differentiate between tuple and tuples proxies, and likewise for
-arrays and array proxies.  We need just one bit to accomplish this,
-and use the bit in position $63$ of the 64-bit tag at the front of
+arrays and array proxies.  We need just one bit to accomplish this;
+we use the bit in position $63$ of the 64-bit tag at the front of
 every tuple (see figure~\ref{fig:tuple-rep}) or array
 every tuple (see figure~\ref{fig:tuple-rep}) or array
 (section~\ref{sec:array-rep}). So far, this bit has been set to $0$,
 (section~\ref{sec:array-rep}). So far, this bit has been set to $0$,
 so for \racket{\code{inject-vector}}\python{\code{InjectTuple}} we leave
 so for \racket{\code{inject-vector}}\python{\code{InjectTuple}} we leave
@@ -20681,11 +20682,12 @@ movq %r11, |$\itm{lhs'}$|
   of the tag and also bit $62$, to differentiate between arrays and tuples.}
   of the tag and also bit $62$, to differentiate between arrays and tuples.}
 
 
 The \racket{\code{proxy?} operation consumes}
 The \racket{\code{proxy?} operation consumes}
-\python{\code{is\_tuple\_proxy} and \code{is\_array\_proxy} operations consume}
-the information so carefully
-stashed away by the injections.  It
-isolates the $63$rd bit to tell whether the value is a tuple/array or
-a proxy.
+\python{\code{is\_tuple\_proxy} and \code{is\_array\_proxy} operations
+  consume}
+%
+the information so carefully stashed away by the injections.  It
+isolates bit $63$ to tell whether the value is a tuple/array or a
+proxy.
 %
 %
 {\if\edition\racketEd
 {\if\edition\racketEd
 \begin{lstlisting}
 \begin{lstlisting}
@@ -20717,7 +20719,7 @@ straightforward to translate, so we leave that to the reader.
 
 
 Regarding the element access operations for tuples and arrays, the
 Regarding the element access operations for tuples and arrays, the
 runtime provides procedures that implement them (they are recursive
 runtime provides procedures that implement them (they are recursive
-functions!)  so here we simply need to translate these tuple
+functions!), so here we simply need to translate these tuple
 operations into the appropriate function call. For example, here is
 operations into the appropriate function call. For example, here is
 the translation for
 the translation for
 \racket{\code{proxy-vector-ref}}\python{\code{proxy\_tuple\_load}}.
 \racket{\code{proxy-vector-ref}}\python{\code{proxy\_tuple\_load}}.
@@ -20749,7 +20751,7 @@ to \code{proxy\_vecof\_set}, and
 \racket{\code{proxy-vectof-length}}\python{\code{proxy\_array\_len}}
 \racket{\code{proxy-vectof-length}}\python{\code{proxy\_array\_len}}
 to \code{proxy\_vecof\_length}.
 to \code{proxy\_vecof\_length}.
 
 
-We have another batch of operations to deal with, those for the
+We have another batch of operations to deal with: those for the
 \CANYTY{} type. Recall that overload resolution
 \CANYTY{} type. Recall that overload resolution
 (section~\ref{sec:gradual-resolution}) generates an
 (section~\ref{sec:gradual-resolution}) generates an
 \racket{\code{any-vector-ref}}\python{\code{any\_load\_unsafe}} when
 \racket{\code{any-vector-ref}}\python{\code{any\_load\_unsafe}} when
@@ -20758,7 +20760,7 @@ similarly for
 \racket{\code{any-vector-set!}}\python{\code{any\_store\_unsafe}} and
 \racket{\code{any-vector-set!}}\python{\code{any\_store\_unsafe}} and
 \racket{\code{any-vector-length}}\python{\code{any\_len}}. In
 \racket{\code{any-vector-length}}\python{\code{any\_len}}. In
 section~\ref{sec:select-Lany} we selected instructions for these
 section~\ref{sec:select-Lany} we selected instructions for these
-operations based on the idea that the underlying value was a tuple or
+operations on the basis of the idea that the underlying value was a tuple or
 array. But in the current setting, the underlying value is of type
 array. But in the current setting, the underlying value is of type
 \PTUPLETYNAME{} or \PARRAYTYNAME{}.  We have added two runtime
 \PTUPLETYNAME{} or \PARRAYTYNAME{}.  We have added two runtime
 functions to deal with this: \code{proxy\_vec\_ref},
 functions to deal with this: \code{proxy\_vec\_ref},
@@ -20770,7 +20772,7 @@ tuples (e.g. \code{proxy\_vector\_ref}) or arrays
 (e.g. \code{proxy\_vecof\_ref}).
 (e.g. \code{proxy\_vecof\_ref}).
 %
 %
 So \racket{\code{any-vector-ref}}\python{\code{any\_load\_unsafe}}
 So \racket{\code{any-vector-ref}}\python{\code{any\_load\_unsafe}}
-can be translated follows.
+can be translated as follows.
 We begin by projecting the underlying value out of the tagged value and
 We begin by projecting the underlying value out of the tagged value and
 then call the \code{proxy\_vec\_ref} procedure in the runtime.
 then call the \code{proxy\_vec\_ref} procedure in the runtime.
 {\if\edition\racketEd
 {\if\edition\racketEd
@@ -20803,18 +20805,18 @@ the \code{proxy\_vec\_ref}, \code{proxy\_vec\_set},
 and \code{proxy\_vec\_length} functions.
 and \code{proxy\_vec\_length} functions.
 
 
 \begin{exercise}\normalfont\normalsize
 \begin{exercise}\normalfont\normalsize
-  Implement a compiler for the gradually-typed \LangGrad{} language by
-  extending and adapting your compiler for \LangLam{}. Create 10 new
-  partially-typed test programs. In addition to testing with these
-  new programs, also test your compiler on all the tests for \LangLam{}
+  Implement a compiler for the gradually typed \LangGrad{} language by
+  extending and adapting your compiler for \LangLam{}. Create ten new
+  partially typed test programs. In addition to testing with these
+  new programs, test your compiler on all the tests for \LangLam{}
   and for \LangDyn{}.
   and for \LangDyn{}.
 %
 %
   \racket{Sometimes you may get a type checking error on the
   \racket{Sometimes you may get a type checking error on the
-    \LangDyn{} programs but you can adapt them by inserting a cast to
-    the \CANYTY{} type around each subexpression causing a type
-    error. While \LangDyn{} does not have explicit casts, you can
+    \LangDyn{} programs, but you can adapt them by inserting a cast to
+    the \CANYTY{} type around each subexpression that has caused a type
+    error. Although \LangDyn{} does not have explicit casts, you can
     induce one by wrapping the subexpression \code{e} with a call to
     induce one by wrapping the subexpression \code{e} with a call to
-    an un-annotated identity function, like this: \code{((lambda (x) x) e)}.}
+    an unannotated identity function, as follows: \code{((lambda (x) x) e)}.}
 %
 %
   \python{Sometimes you may get a type checking error on the
   \python{Sometimes you may get a type checking error on the
     \LangDyn{} programs but you can adapt them by inserting a
     \LangDyn{} programs but you can adapt them by inserting a
@@ -20825,72 +20827,72 @@ and \code{proxy\_vec\_length} functions.
 \begin{figure}[p]
 \begin{figure}[p]
 \begin{tcolorbox}[colback=white]  
 \begin{tcolorbox}[colback=white]  
 \begin{tikzpicture}[baseline=(current  bounding  box.center),scale=0.85]
 \begin{tikzpicture}[baseline=(current  bounding  box.center),scale=0.85]
-\node (Lgradual) at (12,4)  {\large \LangGrad{}};
-\node (Lgradual2) at (9,4)  {\large \LangGrad{}};
-\node (Lgradual3) at (6,4)  {\large \LangCast{}};
-\node (Lgradual4) at (3,4)  {\large \LangProxy{}};
-\node (Lgradualr) at (0,4)  {\large \LangPVec{}};
-\node (Lgradualp) at (0,2)  {\large \LangPVec{}};
-\node (Llambdapp) at (3,2)  {\large \LangPVec{}};
-\node (Llambdaproxy-4) at (6,2)  {\large \LangPVecFunRef{}};
-\node (Llambdaproxy-5) at (9,2)  {\large \LangPVecFunRef{}};
-\node (F1-1) at (12,2)  {\large \LangPVecFunRef{}};
-\node (F1-2) at (12,0)  {\large \LangPVecFunRef{}};
-\node (F1-3) at (9,0)  {\large \LangPVecFunRef{}};
-\node (F1-4) at (6,0)  {\large \LangPVecAlloc{}};
-\node (F1-5) at (3,0)  {\large \LangPVecAlloc{}};
-\node (F1-6) at (0,0)  {\large \LangPVecAlloc{}};
-\node (C3-2) at (3,-2)  {\large \LangCLoopPVec{}};
+\node (Lgradual) at (0,4)  {\large \LangGrad{}};
+\node (Lgradual2) at (4,4)  {\large \LangGrad{}};
+\node (Lgradual3) at (8,4)  {\large \LangCast{}};
+\node (Lgradual4) at (12,4)  {\large \LangProxy{}};
+\node (Lgradualr) at (12,2)  {\large \LangPVec{}};
+\node (Lgradualp) at (8,2)  {\large \LangPVec{}};
+\node (Llambdapp) at (4,2)  {\large \LangPVec{}};
+\node (Llambdaproxy-4) at (0,2)  {\large \LangPVecFunRef{}};
+\node (Llambdaproxy-5) at (0,0)  {\large \LangPVecFunRef{}};
+\node (F1-1) at (4,0)  {\large \LangPVecFunRef{}};
+\node (F1-2) at (8,0)  {\large \LangPVecFunRef{}};
+\node (F1-3) at (12,0)  {\large \LangPVecFunRef{}};
+\node (F1-4) at (12,-2)  {\large \LangPVecAlloc{}};
+\node (F1-5) at (8,-2)  {\large \LangPVecAlloc{}};
+\node (F1-6) at (4,-2)  {\large \LangPVecAlloc{}};
+\node (C3-2) at (0,-2)  {\large \LangCLoopPVec{}};
 
 
-\node (x86-2) at (3,-4)  {\large \LangXIndCallVar{}};
-\node (x86-2-1) at (3,-6)  {\large \LangXIndCallVar{}};
-\node (x86-2-2) at (6,-6)  {\large \LangXIndCallVar{}};
-\node (x86-3) at (6,-4)  {\large \LangXIndCallVar{}};
-\node (x86-4) at (9,-4) {\large \LangXIndCall{}};
-\node (x86-5) at (9,-6) {\large \LangXIndCall{}};
+\node (x86-2) at (0,-4)  {\large \LangXIndCallVar{}};
+\node (x86-2-1) at (0,-6)  {\large \LangXIndCallVar{}};
+\node (x86-2-2) at (4,-6)  {\large \LangXIndCallVar{}};
+\node (x86-3) at (4,-4)  {\large \LangXIndCallVar{}};
+\node (x86-4) at (8,-4) {\large \LangXIndCall{}};
+\node (x86-5) at (8,-6) {\large \LangXIndCall{}};
 
 
 
 
-\path[->,bend right=15] (Lgradual) edge [above] node
+\path[->,bend left=15] (Lgradual) edge [above] node
      {\ttfamily\footnotesize shrink} (Lgradual2);
      {\ttfamily\footnotesize shrink} (Lgradual2);
-\path[->,bend right=15] (Lgradual2) edge [above] node
+\path[->,bend left=15] (Lgradual2) edge [above] node
      {\ttfamily\footnotesize uniquify} (Lgradual3);
      {\ttfamily\footnotesize uniquify} (Lgradual3);
-\path[->,bend right=15] (Lgradual3) edge [above] node
+\path[->,bend left=15] (Lgradual3) edge [above] node
      {\ttfamily\footnotesize reveal\_functions} (Lgradual4);
      {\ttfamily\footnotesize reveal\_functions} (Lgradual4);
-\path[->,bend right=15] (Lgradual4) edge [above] node
+\path[->,bend left=15] (Lgradual4) edge [left] node
      {\ttfamily\footnotesize resolve} (Lgradualr);
      {\ttfamily\footnotesize resolve} (Lgradualr);
-\path[->,bend right=15] (Lgradualr) edge [right] node
+\path[->,bend left=15] (Lgradualr) edge [below] node
      {\ttfamily\footnotesize cast\_insert} (Lgradualp);
      {\ttfamily\footnotesize cast\_insert} (Lgradualp);
-\path[->,bend right=15] (Lgradualp) edge [below] node
+\path[->,bend right=15] (Lgradualp) edge [above] node
      {\ttfamily\footnotesize lower\_casts} (Llambdapp);
      {\ttfamily\footnotesize lower\_casts} (Llambdapp);
-\path[->,bend left=15] (Llambdapp) edge [above] node
-     {\ttfamily\footnotesize differentiate.} (Llambdaproxy-4);
-\path[->,bend left=15] (Llambdaproxy-4) edge [above] node
+\path[->,bend right=15] (Llambdapp) edge [above] node
+     {\ttfamily\footnotesize differentiate\_proxies} (Llambdaproxy-4);
+\path[->,bend right=15] (Llambdaproxy-4) edge [right] node
      {\ttfamily\footnotesize reveal\_casts} (Llambdaproxy-5);
      {\ttfamily\footnotesize reveal\_casts} (Llambdaproxy-5);
-\path[->,bend left=15] (Llambdaproxy-5) edge [above] node
+\path[->,bend right=15] (Llambdaproxy-5) edge [below] node
      {\ttfamily\footnotesize convert\_assignments} (F1-1);
      {\ttfamily\footnotesize convert\_assignments} (F1-1);
-\path[->,bend left=15] (F1-1) edge [left] node
-     {\ttfamily\footnotesize convert\_to\_clos.} (F1-2);
-\path[->,bend left=15] (F1-2) edge [below] node
-     {\ttfamily\footnotesize limit\_fun.} (F1-3);
-\path[->,bend right=15] (F1-3) edge [above] node
-     {\ttfamily\footnotesize expose\_alloc.} (F1-4);
-\path[->,bend right=15] (F1-4) edge [above] node
+\path[->,bend left=15] (F1-1) edge [above] node
+     {\ttfamily\footnotesize convert\_to\_closures} (F1-2);
+\path[->,bend left=15] (F1-2) edge [above] node
+     {\ttfamily\footnotesize limit\_functions} (F1-3);
+\path[->,bend left=15] (F1-3) edge [left] node
+     {\ttfamily\footnotesize expose\_allocation} (F1-4);
+\path[->,bend left=15] (F1-4) edge [below] node
      {\ttfamily\footnotesize uncover\_get!} (F1-5);
      {\ttfamily\footnotesize uncover\_get!} (F1-5);
 \path[->,bend right=15] (F1-5) edge [above] node
 \path[->,bend right=15] (F1-5) edge [above] node
-     {\ttfamily\footnotesize remove\_complex.} (F1-6);
-\path[->,bend right=15] (F1-6) edge [right] node
+     {\ttfamily\footnotesize remove\_complex\_operands} (F1-6);
+\path[->,bend right=15] (F1-6) edge [above] node
      {\ttfamily\footnotesize explicate\_control} (C3-2);
      {\ttfamily\footnotesize explicate\_control} (C3-2);
-\path[->,bend left=15] (C3-2) edge [left] node
-     {\ttfamily\footnotesize select\_instr.} (x86-2);
-\path[->,bend right=15] (x86-2) edge [left] node
+\path[->,bend right=15] (C3-2) edge [right] node
+     {\ttfamily\footnotesize select\_instructions} (x86-2);
+\path[->,bend right=15] (x86-2) edge [right] node
      {\ttfamily\footnotesize uncover\_live} (x86-2-1);
      {\ttfamily\footnotesize uncover\_live} (x86-2-1);
 \path[->,bend right=15] (x86-2-1) edge [below] node 
 \path[->,bend right=15] (x86-2-1) edge [below] node 
-     {\ttfamily\footnotesize build\_inter.} (x86-2-2);
-\path[->,bend right=15] (x86-2-2) edge [left] node
-     {\ttfamily\footnotesize allocate\_reg.} (x86-3);
+     {\ttfamily\footnotesize build\_interference} (x86-2-2);
+\path[->,bend right=15] (x86-2-2) edge [right] node
+     {\ttfamily\footnotesize allocate\_registers} (x86-3);
 \path[->,bend left=15] (x86-3) edge [above] node
 \path[->,bend left=15] (x86-3) edge [above] node
-     {\ttfamily\footnotesize patch\_instr.} (x86-4);
-\path[->,bend left=15] (x86-4) edge [right] node {\ttfamily\footnotesize prelude\_and\_conc.} (x86-5);
+     {\ttfamily\footnotesize patch\_instructions} (x86-4);
+\path[->,bend left=15] (x86-4) edge [right] node {\ttfamily\footnotesize prelude\_and\_conclusion} (x86-5);
 \end{tikzpicture}
 \end{tikzpicture}
 \end{tcolorbox}
 \end{tcolorbox}
 
 
@@ -20917,27 +20919,27 @@ original location of the cast in the source program.
 
 
 The problem addressed by space-efficient casts also relates to
 The problem addressed by space-efficient casts also relates to
 higher-order casts. It turns out that in partially typed programs, a
 higher-order casts. It turns out that in partially typed programs, a
-function or tuple can flow through very many casts at runtime. With
+function or tuple can flow through a great many casts at runtime. With
 the approach described in this chapter, each cast adds another
 the approach described in this chapter, each cast adds another
 \code{lambda} wrapper or a tuple proxy. Not only does this take up
 \code{lambda} wrapper or a tuple proxy. Not only does this take up
 considerable space, but it also makes the function calls and tuple
 considerable space, but it also makes the function calls and tuple
-operations slow.  For example, a partially-typed version of quicksort
+operations slow.  For example, a partially typed version of quicksort
 could, in the worst case, build a chain of proxies of length $O(n)$
 could, in the worst case, build a chain of proxies of length $O(n)$
 around the tuple, changing the overall time complexity of the
 around the tuple, changing the overall time complexity of the
 algorithm from $O(n^2)$ to $O(n^3)$! \citet{Herman:2006uq} suggested a
 algorithm from $O(n^2)$ to $O(n^3)$! \citet{Herman:2006uq} suggested a
 solution to this problem by representing casts using the coercion
 solution to this problem by representing casts using the coercion
 calculus of \citet{Henglein:1994nz}, which prevents the creation of
 calculus of \citet{Henglein:1994nz}, which prevents the creation of
 long chains of proxies by compressing them into a concise normal
 long chains of proxies by compressing them into a concise normal
-form. \citet{Siek:2015ab} give an algorithm for compressing coercions
+form. \citet{Siek:2015ab} give an algorithm for compressing coercions,
 and \citet{Kuhlenschmidt:2019aa} show how to implement these ideas in
 and \citet{Kuhlenschmidt:2019aa} show how to implement these ideas in
-the Grift compiler.
+the Grift compiler:
 \begin{center}
 \begin{center}
   \url{https://github.com/Gradual-Typing/Grift}
   \url{https://github.com/Gradual-Typing/Grift}
 \end{center}
 \end{center}
 
 
 There are also interesting interactions between gradual typing and
 There are also interesting interactions between gradual typing and
 other language features, such as generics, information-flow types, and
 other language features, such as generics, information-flow types, and
-type inference, to name a few. We recommend the reader to consult the
+type inference, to name a few. We recommend to the reader the
 online gradual typing bibliography for more material:
 online gradual typing bibliography for more material:
 \begin{center}
 \begin{center}
   \url{http://samth.github.io/gradual-typing-bib/}
   \url{http://samth.github.io/gradual-typing-bib/}