trivial/popl-2017/examples.scrbl
2016-06-27 16:00:01 -04:00

184 lines
7.3 KiB
Racket

#lang scribble/sigplan @onecolumn
@require["common.rkt"]
@title[#:tag "sec:examples"]{Small Things and Great}
@; He that lets
@; the small things bind him
@; leaves the great
@; undone behind him.
@Figure-ref{fig:expr} defines an untyped, call-by-value @racket[λ] calculus
augmented with boolean, character, natural number, and vector literals.
The language also includes a set @exact{$\primop$} of primitive operations,
described in @Figure-ref{fig:primop} and a labeled error term @exact{$\bot$}.
For the moment we focus on two primitive operations: @racket[ref], for dereferencing
a vector, and @racket[map], for mapping a function of arity @exact{$m$} over
the columns of an @exact{$m \times n$} matrix.
We specify these operations with an informal mathematical syntax using
@racket[] and @racket[=] to dynamically test and pattern match value forms.
@figure["fig:expr" "Term language"
@exact|{\input{fig-language}}|
]
@figure["fig:primop" "Primitive operations"
@exact|{\input{fig-primops}}|
]
This language is intended to model the untyped core of realistic
languages like ML, Haskell, and Typed Racket; albiet using @exact{$\lambda$}
notation instead of a machine language.
Likewise, the polymorphic type system in @Figure-ref{fig:types} is a standard,
implicitly quantified system.
@; These types are CLEARLY LIMITED in what they can express,
@; but even TR, ML+1stclassmodules, GHC+extensions have limitations
@; tho less obvious
@figure["fig:types" "Type System"
@exact|{\input{fig-types}}|
]
@figure["fig:typed-primops" "Typed Primitive Operations"
@exact|{\input{fig-typed-primops}}|
]
Using this type system, we can approximate the behavior of @racket[ref] and
@racket[map] with the signatures in @Figure-ref{fig:typed-primops}.
The type @exact|{$\tau_{\RktMeta{ref}}$}| captures the essence of @racket[ref],
but does not express the requirement that @emph{value} of the number
@racket[i] in a call @exact|{\RktMeta{(ref~v~i)}}|
must be strictly less than the length of the vector @racket[v].
The type @exact|{$\tau_{\RktMeta{map}}$}|, on the other hand,
is limited compared to the untyped @racket[map] because there is no way
to apply a typed function to an unknown number of arguments.@note{Curried functions
run into the same limitation.}
@;Try implementing @racket[apply f (x1 \ldots xn) = f x1 \ldots xn}.
Realistic languages would account for at least the 2-arity case with a second
function @exact|{$\RktMeta{map}_2$}| and ask programmers
to choose between @racket[map] and @exact|{$\RktMeta{map}_2$}| at each call site.
This inability of the type system to express our specifications is a problem.
@section{Refining the Imprecise Types}
There is no reason we could not revise our type system to make
it possible to track the length of vectors and express polymorphism over
the arity of functions.
In fact, GHC can express the type of fixed-length vectors@~cite[lb-sigplan-2014] and Typed Racket
supports variable-arity polymorphism@~cite[stf-esop-2009].
But such revisions are sweeping changes to the type system and therefore the
language.
Moreover, programmers who use the language to create embedded DSLs may
wish to encode novel type constraints, as we demonstrate in @Secref{sec:regexp}.
Rather than alter the type system or accept the status quo,
we add the syntax extension system shown in @Figure-ref{fig:syntax-base}.
To underscore the fact that syntax extensions are run on syntactic terms
rather than runtime values, we format the system as a collection of
inference rules.
In practice, we could implement these rules with a pattern matcher like
Racket's @racket[syntax-parse].
@; Users extend by:
@; - inhertance, modifying definition of a "parser" object
@; - use parameter for recursive call, users update parameter
Define @exact{$\elaborate(e) = e'$} if and only if @exact{$e \expandsto e'$}.
As presented in @Figure-ref{fig:syntax-base}, @exact{$\elaborate$} is a structurally
recursive identity function.
Still, it satisfies three key properties (the 3 R's of reasonable syntax extensions).
Let @exact{$\Downarrow$}
implicitly quantify over closing substitutions @exact{$\gamma$}.
@figure["fig:syntax-base" "Default Syntax Extensions"
@exact|{\input{fig-syntax-base.tex}}|
]
@theorem["Refinement"]{
If @exact{$\vdash e : \tau$} then @exact{$\vdash \elaborate(e) : \tau'$}
and @exact{$\tau' <: \tau$}.
Furthermore @exact{$e \Downarrow v$} if and only if @exact{$\elaborate(e) \Downarrow v$}.
}
In other words, elaboration may make the type of a well-typed term more precise.
(Use type equality in place of @exact{$<:$} for now)
@theorem["Retraction"]{
If @exact{$\not \exists \tau~.~\vdash e : \tau$} but @exact{$\vdash \elaborate(e) : \tau'$}
then @exact{$e \Downarrow v$} if and only if @exact{$\elaborate(e) \Downarrow v$}.
}
Desugaring a term to make it type check does not change its dynamic behavior.
(Holds trivially because its premise is never met.)
@theorem["Relevance"]{
If @exact|{$\elaborate(e) = \bot^{e'}$}| then @exact{$e'$} is a subterm of @exact{$e$}
and evaluating @exact{$e'$} (but not necessarily @exact{$e$}) raises a runtime error.
}
Elaboration errors always reflect defects in the user's code and are presented
using source terms rather than expanded terms.
(Holds because the current version of @exact{$\elaborate$} never yields an error term.)
We claim that these theorems enable reasoning about un-elaborated terms
using the familiar type system and semantics from @Figure-ref["fig:expr" "fig:types"].
Henceforth, we say that a term @racket[e] typechecks in the extended language
(written @exact{$\vdashe e : \tau$})
if there exists a type @exact{$\tau$} such that @exact|{$\Gamma_{\primop} \vdash \elaborate(e) : \tau$}|.
A term @racket[e] evaluates to a value @racket[v] in the extended language
(@exact{$e \Downarrowe v$}) if and only if @exact{$\elaborate(e) \Downarrow v$}.
The crucial feature of @exact{$\elaborate$} is that language users can add
cases to it.
Changing roles from language designers to language users, we leverage this
ability in the next sections based on the intuition that the syntax
of value forms carries information.
@section{Bounds Checking for @racket[ref]}
For a first extension, we can check vector references at compile-time when
@racket[ref] is called with a vector literal and a natural number.
To accomodate future syntax extensions, we recursively expand the arguments to
our @racket[ref] extension before checking.
@exact|{
\begin{mathpar}
\inferrule{
v \expandsto \vectoren
\\
i \expandsto i'
\\\\
i' \in \naturals
\\
i' < n
}{
\RktMeta{ref}~v~i \expandsto \RktMeta{ref}~\vectoren~i
}
\end{mathpar}
}|
When this condition is not met,
@section{Typed, Generalized @racket[map]}
@section[#:tag "sec:regexp"]{Adding Regular Expressions}
@; - string-embedded DSL
@; - NOT part of core language, just ideas from crazy library writer
@; - refine codomain of an operation
We assume @exact{$\Sigma$} is just the lowercase characters @exact{$a \ldots z$}.
To keep the language small, we define strings as vectors of characters
and use e.g. @racket{abc} as shorthand for @exact|{$\vectorgen{a, b, c}$}|.
@section[#:tag "sec:define"]{Handling Variables}
@; Add a type system --- thanks Alex!