[icfp] explain tagging, kinda formally
This commit is contained in:
parent
1686bc310d
commit
a141456b52
|
@ -1,13 +1,4 @@
|
||||||
#lang scribble/sigplan @onecolumn
|
#lang scribble/sigplan @onecolumn
|
||||||
@; TODO
|
|
||||||
@; - stephen: too vague!
|
|
||||||
@; - sam : too vague!
|
|
||||||
@; : can you give more example?
|
|
||||||
@; : too generous to other languages -- why didn't you do the entire paper in hs?
|
|
||||||
@; - a note on macro-land? where truthy & boolean monads are king?
|
|
||||||
@; - also, the untyped style of reasoning, the needing to unfold code
|
|
||||||
@; - transf vs. macro
|
|
||||||
@; - remove "OUR"
|
|
||||||
|
|
||||||
|
|
||||||
@require["common.rkt"]
|
@require["common.rkt"]
|
||||||
|
@ -19,12 +10,12 @@ Well-typed programs @emph{do} go wrong.
|
||||||
All the time, in fact:
|
All the time, in fact:
|
||||||
|
|
||||||
@codeblock{
|
@codeblock{
|
||||||
> (vector-ref (build-vector 2 (λ (i) i)) 3)
|
> (vector-ref (make-vector 2) 3)
|
||||||
; vector-ref: index is out of range
|
==> vector-ref: index is out of range
|
||||||
> (/ 1 0)
|
> (/ 1 0)
|
||||||
; /: division by zero
|
==> /: division by zero
|
||||||
> (printf "~s")
|
> (printf "~s")
|
||||||
; printf: format string requires 1 arguments, given 0
|
==> printf: format string requires 1 arguments, given 0
|
||||||
}
|
}
|
||||||
|
|
||||||
Of course, Milner's catchphrase was about preventing type errors.
|
Of course, Milner's catchphrase was about preventing type errors.
|
||||||
|
@ -47,7 +38,7 @@ The standard work-around@~cite[fi-jfp-2000] is to maintain size-indexed
|
||||||
These problems are well known, and are often used to motivate research on
|
These problems are well known, and are often used to motivate research on
|
||||||
dependently typed programming languages@~cite[a-icfp-1999].
|
dependently typed programming languages@~cite[a-icfp-1999].
|
||||||
Short of abandoning ship for a completely new type system, languages including
|
Short of abandoning ship for a completely new type system, languages including
|
||||||
Haskell, OCaml, Java, and Typed Racket have seen proposals for detecting
|
Haskell, Java, OCaml, and Typed Racket have seen proposals for detecting
|
||||||
certain values errors or expressing the polymorphism in functions
|
certain values errors or expressing the polymorphism in functions
|
||||||
such as @racket[curry] with few (if any) changes to the existing type system@~cite[ddems-icse-2011 ks-plpv-2006 kkt-pldi-2016 lb-sigplan-2014].
|
such as @racket[curry] with few (if any) changes to the existing type system@~cite[ddems-icse-2011 ks-plpv-2006 kkt-pldi-2016 lb-sigplan-2014].
|
||||||
What stands between these proposals and their adoption is the complexity or
|
What stands between these proposals and their adoption is the complexity or
|
||||||
|
@ -62,13 +53,13 @@ The key is to run a @emph{textualist}@note{A textualist interprets laws by
|
||||||
evident from the program syntax to the type checker.
|
evident from the program syntax to the type checker.
|
||||||
In terms of the first example in this section, our elaborator infers that the
|
In terms of the first example in this section, our elaborator infers that the
|
||||||
@racket[vector-ref] at position @racket[3] is out of bounds because it knows that
|
@racket[vector-ref] at position @racket[3] is out of bounds because it knows that
|
||||||
@racket[(build-vector n f)]
|
@racket[(make-vector n)]
|
||||||
constructs a vector with @racket[n] elements.
|
constructs a vector with @racket[n] elements.
|
||||||
|
|
||||||
Our implementation is a Typed Racket library that shadows functions
|
Our implementation is a Typed Racket library that shadows functions
|
||||||
such as @racket[build-vector] with textualist elaborators following the
|
such as @racket[build-vector] with textualist elaborators following the
|
||||||
guidelines stated in @Secref{sec:solution}.
|
guidelines stated in @Secref{sec:solution}.
|
||||||
We make essential use of Racket's powerful macro system@~cite[fcdb-jfp-2012]
|
We make essential use of Racket's macro system@~cite[fcdb-jfp-2012]
|
||||||
to reason locally, associate inferred data with bound identifiers, and
|
to reason locally, associate inferred data with bound identifiers, and
|
||||||
cooperate with the rules of lexical scope.
|
cooperate with the rules of lexical scope.
|
||||||
For the adventurous reader, @Secref{sec:implementation} describes the
|
For the adventurous reader, @Secref{sec:implementation} describes the
|
||||||
|
@ -97,11 +88,12 @@ We have written an elaborator for @racket[regexp-match] that will statically
|
||||||
The elaborator also handles the common case where the regular expression
|
The elaborator also handles the common case where the regular expression
|
||||||
argument is a compile-time constant and respects @exact{$\alpha$}-equivalence.
|
argument is a compile-time constant and respects @exact{$\alpha$}-equivalence.
|
||||||
|
|
||||||
|
In sum, the code below will compile using our library's @racket[regexp-match]
|
||||||
|
whereas Typed Racket cannot guarantee the call to @racket[second] will produce
|
||||||
|
a string.
|
||||||
|
|
||||||
@codeblock{
|
@codeblock{
|
||||||
(define rx-case #rx"(.*) v\\. (.*),")
|
(define rx-case #rx"(.*) v\\. (.*),")
|
||||||
|
|
||||||
; Other code here
|
|
||||||
|
|
||||||
(define r-m regexp-match)
|
(define r-m regexp-match)
|
||||||
|
|
||||||
(define (get-plaintiff (s : String)) : String
|
(define (get-plaintiff (s : String)) : String
|
||||||
|
@ -114,17 +106,3 @@ The elaborator also handles the common case where the regular expression
|
||||||
@Secref{sec:usage} has more examples.
|
@Secref{sec:usage} has more examples.
|
||||||
@Secref{sec:conclusion} concludes.
|
@Secref{sec:conclusion} concludes.
|
||||||
|
|
||||||
@; =============================================================================
|
|
||||||
|
|
||||||
@parag{Lineage}
|
|
||||||
|
|
||||||
Herman and Meunier demonstrated how Racket macros can propagate
|
|
||||||
data embedded in string values and syntax patterns to a
|
|
||||||
static analyzer@~cite[hm-icfp-2004].
|
|
||||||
Their illustrative examples were format strings, regular expressions,
|
|
||||||
and database queries.
|
|
||||||
Relative to their pioneering work, we adapt Herman & Meunier's
|
|
||||||
transformations to a typed language by inserting type annotations and boolean
|
|
||||||
guards into the programs.
|
|
||||||
Our treatment of definition forms is also new.
|
|
||||||
|
|
||||||
|
|
|
@ -101,3 +101,22 @@ In a perfect world both would diverge, but the fundamental limitations of
|
||||||
At present, these correctness requirements must be checked manually by the
|
At present, these correctness requirements must be checked manually by the
|
||||||
author of a function in @exact{$\interp$} or @exact{$\elab$}.
|
author of a function in @exact{$\interp$} or @exact{$\elab$}.
|
||||||
|
|
||||||
|
|
||||||
|
@; =============================================================================
|
||||||
|
@section{Cooperative Elaboration}
|
||||||
|
|
||||||
|
Suppose we implement a currying operation
|
||||||
|
@exact{$\elabf$} such that e.g.
|
||||||
|
@exact{$\llbracket$}@racket[(curry (λ (x y) x))]@exact{$\rrbracket~=~$}@racket[(curry_2 (λ (x y) x))].
|
||||||
|
The arity of @racket[(λ (x y) x)] is clear from its representation.
|
||||||
|
The arity of the result could also be derived from its textual representation,
|
||||||
|
but it is simpler to @emph{tag} the result such that future elaborations
|
||||||
|
can retrieve the arity of @racket[(curry_2 (λ (x y) x))].
|
||||||
|
|
||||||
|
Our implementation uses a tagging protocol, and this lets us share information
|
||||||
|
between unrelated elaboration function in a bottom-up recursive style.
|
||||||
|
The same protocol helps us implement binding forms: when interpreting a variable,
|
||||||
|
we check for an associated tag.
|
||||||
|
Formally speaking, this either changes the codomain of functions in @exact{$\elab$}
|
||||||
|
or introduces an elaboration environment mapping expressions to values.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user