λk.(k blog): Posts tagged 'research'urn:https-www-williamjbowman-com:-tags-research-html2018-01-19T23:37:01ZUntyped Programs Don't Existurn:https-www-williamjbowman-com:-blog-2018-01-19-untyped-programs-don-t-exist2018-01-19T23:37:01Z2018-01-19T23:37:01ZWilliam J. Bowman
<p>Lately, I’ve been thinking about various (false) dichotomies, such as typed vs untyped programming and type systems vs program logics. In this blog post, I will argue that untyped programs don’t exist (although the statement will turn out to be trivial).</p>
<p><a id="orgf07fde6"></a></p>
<h4 id="tldr">TLDR</h4>
<p>All languages are typed, but may use different enforcement mechanisms (static checking, dynamic checking, no checking, or some combination). We should talk about how to use types in programming—<em>e.g.</em> tools for writing and enforcing invariants about programs—instead of talking about types and type checking as properties of languages.</p>
<!-- more-->
<h2 id="table-of-contents">Table of Contents</h2>
<div id="table-of-contents">
<div id="text-table-of-contents">
<ul>
<li><a href="#orgf07fde6">1. TLDR</a></li>
<li><a href="#orgaf4345b">2. Some Context</a></li>
<li><a href="#orgdaebb53">3. Definitions</a></li>
<li><a href="#org124f9c8">4. Is X a Typed Language?</a></li>
<li><a href="#org8701978">5. But I Don't Get Type Errors in X!</a></li>
<li><a href="#orgbd43271">6. Untyped Programs Don't Exist.</a></li>
<li><a href="#org53d6b39">7. Conclusion</a></li>
<li><a href="#related">8. Related Reading</a></li></ul></div></div>
<p><a id="orgaf4345b"></a></p>
<h2 id="some-context">Some Context</h2>
<p>In most of my academic work, I work with “typed” languages. These languages have some nice properties for the metatheorist and compiler writer. Types lend themselves to strong automated reasoning, automatically eliminate large classes of errors, and simplify the job of whoever is reasoning about the programs. The downside is that the programmer must essentially statically prove properties of their program in such a way that a machine can understand the theorem and check the proof.</p>
<p>When I’m hacking, I write in “untyped” languages. I write programs in Racket, scripts in bash, plugins and tools in JavaScript, papers in latex, build systems in Makefile, and so on. These languages lend themselves to experimentation and avoid the overhead of necessarily proving properties of the programs. The downside is that the computer cannot help the programmer, since the programmer has not communicated the invariants about the program in a way the computer can understand.</p>
<p>“But surely”, a type evangelist says, “the very same benefits of types for metatheory help one develop the program in the first place? Why do you hobble yourself by omitting types? Come join us in the land of light! Use types from the start!”</p>
<p>“Dear friend, I couldn’t agree more!”, I reply, "Types are invaluable to developing my programs, but your ‘typed’ language <strong>prevent</strong> me from writing down my types!’</p>
<p>"Well, certainly there are some limitations of typed languages," the type evangelist concedes, "but this we could also choose to ignore the type system, create the uni-type, and program in the error monad. Now we have the benefits of both worlds!"</p>
<p>"Don’t you see,", I say excitedly, "that is just what I’m doing! My ‘untyped’ languages are, in fact, well-typed. My programs run implicitly in the error monad. What’s more, I am not required to <strong>prove</strong> it, for it is simply <strong>true</strong>."</p>
<p>A grave look comes over my interlocutor’s face. "But you forfeit all benefits of static typing. Your errors are reported later, and there are performance implications, and …"</p>
<p>"Exactly.", I interrupt. "We are not arguing about typing, for all programs are well typed. We are arguing about pragmatics."</p>
<p><a id="orgdaebb53"></a></p>
<h2 id="definitions">Definitions</h2>
<p>Before I can argue that untyped programs don’t exist, I need some near-formal definitions to work with. I posit the following definitions are reasonable, intuitive definitions about types and programs.</p>
<p><strong>Definition.</strong> An <em>expression</em> is a symbol of sequence of symbols given some interpretation.</p>
<p><strong>Example.</strong></p>
<ul>
<li><code>5</code> is an expression, whose interpretation is the number five.</li>
<li><code>e₁ + e₁</code> is an expression, whose interpretation is the mathematical addition function applied to expressions <code>e₁</code> and <code>e₂</code>.</li>
<li><code>function(): return 5;</code> is an expression, whose interpretation is a mathematical function that when applied to any number of arguments returns the expression <code>5</code>.</li></ul>
<p><strong>Definition.</strong> A <em>type</em> is a statement of the invariants of some expressions.</p>
<p><strong>Example.</strong></p>
<ul>
<li>a <em>register word</em> is a type describing the kinds of values that fit in an x86 register, such as a collection of 32 bits. A register word supports operations such as:
<ul>
<li>move a value of type register word into a register</li>
<li>move a value of type register word from one register into another</li></ul></li>
<li>a <em>pointer</em> is a type describing a memory address. It is either uninitialized or a valid memory address. A pointer supports operations such as:
<ul>
<li>initialization, giving an uninitialized pointer a value</li>
<li>dereference, reading the value of the memory address of an initialized pointer</li></ul></li>
<li>a <em>Nat</em> is a type describing an element of the set of natural numbers. A Nat supports operations such as:
<ul>
<li>addition</li>
<li>multiplication</li>
<li>subtraction, but only when subtracting a smaller natural number from a larger natural number</li></ul></li></ul>
<p><strong>Definition.</strong> A <em>language</em> is collection of expressions.</p>
<p><strong>Example.</strong></p>
<ul>
<li>arith is a language containing the following expressions <em>e</em>:
<ul>
<li><code>0</code>,<code>1</code>,<code>2</code> …, etc and <code>-1</code>,<code>-2</code>,<code>-3</code>, …, etc, each representing an integer</li>
<li><code>e₁ + e₂</code>, where <code>e₁</code> and <code>e₂</code> are integers</li>
<li><code>e₁ - e₂</code>, where <code>e₁</code> and <code>e₂</code> are integers</li></ul></li>
<li>JavaScript is a language, defined by the ECMAScript standard, and extended by various implementations.</li></ul>
<p><strong>Definition.</strong> A <em>program</em> is a collection of expressions from some language.</p>
<p><strong>Example.</strong></p>
<ul>
<li><code>5 + 5</code> is an arith program.</li>
<li><code>5</code> is a JavaScript program.</li></ul>
<p><a id="org124f9c8"></a></p>
<h2 id="is-x-a-typed-language">Is X a Typed Language?</h2>
<p>Is x86 assembly a typed language?</p>
<p>I say yes.</p>
<p>First, x86 assembly is a language. The language x86 assembly meets our definition of a language: it defines a collection of symbols or sequences of symbols given some interpretation. For example, <code>mov ax, bx</code> is an x86 assembly program that moves the contents of register <code>bx</code> to register <code>ax</code>.</p>
<p>Second, x86 is typed. Each expression in x86 assembly has invariants stated about the expression. For example, x86 defines the type “little endian”, which describes the particular encoding of binary data such as numbers over which operations like addition are defined. The division operation is well typed: as division is only defined when the denominator is non-zero. Attempting to divide by zero cause a type error (a dynamic exception).</p>
<p>I would make the same argument for every other language. C is a typed language. So is JavaScript. And Racket. And Haskell.</p>
<p><a id="org8701978"></a></p>
<h2 id="but-i-dont-get-type-errors-in-x">But I Don’t Get Type Errors in X!</h2>
<p>First, you probably do. Second, when you don’t, that’s a major problem.</p>
<p>Let’s visit x86 for a moment, to see dynamically enforced type errors. Recall that division is not defined when the denominator is zero. The result of division by zero in x86 is defined to be a general-protection exception, error code 0. That is a type error. It’s a type error describing that you attempted to divide by zero, and that this is ill-typed. It is a dynamically enforced type error.</p>
<p>Let’s move to C, in which we can easily see two different kinds of type errors: static and unenforced. The language C includes expressions like <code>x=e</code>, where <code>x</code> is a declared name and <code>e</code> is an expression. The expression <code>x=e</code> raises a static error when <code>x</code> is undeclared; this is a static type error. It is a statically enforced invariant that names must be declared before they are used. Other invariants are not enforced at all, such as notorious undefined behavior. For example, <code>bool b; if(b) { ... };</code> violates a C invariants, namely that uninitialized scalars are never used. However, C does not attempt to enforce this invariant, either statically or dynamically. The result of this sequence of symbols is undefined in C.</p>
<p><a id="orgbd43271"></a></p>
<h2 id="untyped-programs-dont-exist">Untyped Programs Don’t Exist</h2>
<p>First, a few more definitions based on the above arguments about the languages x86 and C.</p>
<p><strong>Definition.</strong> A <em>type error</em> is an error raised during the enforcement of a type, <em>i.e.</em>, during the enforcement of an invariant about an expression.</p>
<p><strong>Definition.</strong> <em>Undefined behavior</em> is the result of interpreting a non-expression, <em>i.e.</em>, a sequence of symbols that have no meaning because some invariant has been violated.</p>
<p><strong>Theorem.</strong> Untyped Programs Don’t Exist.</p>
<p><strong>Proof.</strong> Recall that programs consist of expressions from a language. Expressions are sequences of symbols that have meaning. But <em>undefined behavior</em> only results from non-expressions. As programs are composed of expressions, a program cannot have undefined behavior. Therefore, all programs obey the invariants required by the expressions in the language. That is, all programs are well typed, and untyped programs don’t exist. <strong>QED.</strong></p>
<p>I warned you it was a trivial theorem.</p>
<p><a id="org53d6b39"></a></p>
<h2 id="conclusion">Conclusion</h2>
<p>The theorem is trivial, but still useful because it helps us reframe our discussion.</p>
<p>Really, the statement is just a rephrasing of type safety: “well typed programs don’t go wrong”. For type safety, what we show is that programs exhibit only defined behavior. The difference is that, typically, type safety is typically thought of as a property of a <em>language</em>, and in particular, of statically typed languages. We should think about type safety differently: it is a property we must enforce of <em>programs</em>. Enforcing it via static typing of every program in the language is one useful way, but it is not the only way, and we cannot always hope to have type safety of a language.</p>
<p>Instead of arguing about untyped vs typed, a non-existent distinction, we should accept that all programs have invariants that must be obeyed, <em>i.e.</em>, all programs are typed. The argument we must have is about the pragmatics of types and type checking.</p>
<ul>
<li>how can we express types about complex languages like x86 and C</li>
<li>under what situations should we enforce types, <em>i.e.</em>, check types</li>
<li>is type checking useful</li>
<li>should we check types statically or dynamically</li>
<li>should we allow the programmer to circumvent types checking</li>
<li>is type checking decidable</li>
<li>should it be</li></ul>
<p><a id="related"></a></p>
<h2 id="related-reading">Related Reading</h2>
<h4 id="httpdxdoiorg107146bricsv7i3220167the-meaning-of-types---from-intrinsic-to-extrinsic-semantics-reynold-2000"><a href="http://dx.doi.org/10.7146/brics.v7i32.20167"><em>The Meaning of Types - From Intrinsic to Extrinsic Semantics</em></a> (Reynold 2000)</h4>
<p>This paper proves equivalence of an intrinsically typed languages in which meaning is only assigned to well-typed programs and an extrinsically typed language in which programs are first given meaning and can separately be ascribed types and proved to inhabit those types. In the extrinsic semantics, Reynold’s treat all programs as existing in the universal domain, and use embedding-projection pairs essentially as contracts at run-time, since, <em>e.g.</em>, only a function can be called. In my mind, this work essentially proves the same theorem as this blog post: even in an when the semantics of programs consider typing as happening “after” semantics, the semantics still require types.</p>
<h4 id="httpsexistentialtypewordpresscom20110319dynamic-languages-are-static-languagesdynamic-languages-are-static-languages-harper-2011"><a href="https://existentialtype.wordpress.com/2011/03/19/dynamic-languages-are-static-languages/"><em>Dynamic Languages are Static Languages</em></a> (Harper 2011)</h4>
<p>This blog post argues that dynamic languages are just straight-jacketed versions of static languages, and therefore they aren’t really a separate class of languages. In many ways, I agree with this blog post. Because “dynamic” languages lack any static enforcement, they can be a hindrance when you do know how to encode the types you want, and they can lead to weird type confusing programming patterns. My favorite example pattern is from Racket, where the value <code>#f</code> is sometimes used at type <code>bool</code> and sometimes at type <code>Maybe A</code>. This can lead to annoying problems with functions like <code>findf</code> over a list of <code>bools</code>. However, I think it ignores some of the pragmatics. For example, while sum types give you incredible expressive power, tagged sums are very annoying to use in many languages that enforce static typing, while very simple to use when you are not required to statically prove a term inhabits a sum.</p>
<h4 id="httpsmediumcomsamthon-typed-untyped-and-uni-typed-languages-8a3b4bedf68con-typed-untyped-and-uni-typed-languages-tobin-hochstadt-2014"><a href="https://medium.com/@samth/on-typed-untyped-and-uni-typed-languages-8a3b4bedf68c"><em>On Typed, Untyped, and Uni-typed Languages</em></a> (Tobin-Hochstadt 2014)</h4>
<p>This blog post begins to get at some of the same criticisms of Harper’s view, and starts to talk about pragmatics.</p>
<h4 id="httpblogsperlorgusersovid201008what-to-know-before-debating-type-systemshtmlwhat-to-know-before-debating-type-systems-smith-2010"><a href="http://blogs.perl.org/users/ovid/2010/08/what-to-know-before-debating-type-systems.html"><em>What to Know Before Debating Type Systems</em></a> (Smith 2010)</h4>
<p>This blog post, reproduced in 2010 on a perl blog, does a great job of breaking down some false dichotomies and fallacies in discussions about type systems. It into more depth than this article about some distinctions in type systems, when they are meaningful and when they are not, and I pretty much agree with it.</p>
<h4 id="httpswww2ccsneueduracketpubsdissertation-felleisenpdfthe-calculi-of-lambda-v-cs-conversion-a-syntactic-theory-of-control-and-state-in-imperative-higher-order-programming-languages-felleisen-1987"><a href="https://www2.ccs.neu.edu/racket/pubs/dissertation-felleisen.pdf"><em>The Calculi of Lambda-v-CS Conversion: A Syntactic Theory of Control and State in Imperative Higher-order Programming Languages</em></a> (Felleisen 1987)</h4>
<p>The abstract and chapter 1 of this dissertation have something to say about syntax and semantics, which I think are very related to the topic of this blog post. In particular, the thoughts on symbolic-syntactic reasoning I think are vital to understanding the trade-offs in different enforcements of typing.</p>
<h4 id="httphomessoicindianaedujsiekwhat-is-gradual-typingwhat-is-gradual-typing-siek-2014"><a href="http://homes.soic.indiana.edu/jsiek/what-is-gradual-typing/"><em>What is Gradual Typing</em></a> (Siek 2014)</h4>
<p>This blog post discusses some trade-offs in static vs dynamic typing, in the context of gradual typing. To me, advancement in gradual typing is crucial in making typing enforcement more pragmatic. However, I disagree with some of the “good points” in this blog post. For example, the point “Dynamic type checking doesn’t get in your way” is a bad point to me; it’s also an argument in favor of no enforcement and undefined behavior. I also find some examples of gradual typing to be great evidence of what is wrong with gradual typing. For example, the program <code>add1(true)</code> at the end of the post should be refuted by a gradual type system, but passes current “plausibility checkers”, even when <code>add1</code> has static type annotations requiring that its argument be a number.</p>The reviewers were right to reject my paperurn:https-www-williamjbowman-com:-blog-2017-10-08-the-reviewers-were-right-to-reject-my-paper2017-10-09T03:22:35Z2017-10-09T03:22:35ZWilliam J. Bowman
<p>I submitted two papers to POPL 2018. The first, <a href="https://williamjbowman.com/papers#cps-sigma">“Type-Preserving CPS Translation of Σ and Π Types is Not Not Possible”</a>, was accepted. The second, “Correctly Closure-Converting Coq and Keeping the Types, Too” (draft unavailable), was rejected.</p>
<p>Initially, I was annoyed about the reviews. I’ve since reconsidered the reviews and my work, and think the reviewers were right: this paper needs more work.</p>
<!-- more-->
<p>In short and in my own words, the reviews criticized my work as follows:</p>
<ol>
<li>The translation requires ad-hoc additions to the target language.</li>
<li>There is no proof of type soundness of the target language.</li>
<li>The work ignores the issue of computational relevance, compiling irrelevant things like functions in Prop.</li>
<li>The key insight is poorly explained, lost in the details of the Calculus of Inductive Constructions (CIC).</li></ol>
<p>Initially, I thought that the reviews were unfair. I had worked out type-preserving closure conversion for much of CIC! We have an argument for why the target ought to be sound, but a formal proof would be too much. It took many dissertations to work out the soundness of CIC! As for computational relevance, well sure, we’re compiling too much, but we’re preserving all the information! Computational relevance is hard; one dissertation has been written on the subject and another is in the works. Figuring out computational relevance is important, but will be a separate project in itself! As for ad-hoc, well, I disagree, but maybe I communicated badly; that’s on me.</p>
<p>And that’s, essentially, what I wrote in my rebuttal. However, now I’m reconsidering my position.</p>
<p>But first, some context.</p>
<p>In this POPL submission, I developed a type-preserving closure conversion for CIC. An early version of this work was presented as a student research competition poster at POPL 2017, which you can find at <a href="https://williamjbowman.com/papers#cccc-popl17-src">here</a>. In this paper, I scaled that work from the Calculus of Constructions to CIC; I added inductive types, guarded recursion, the universe hierarchy, and Set vs Prop. To do that, I made some compromises. I decided not to formally prove soundness, but give an argument thusly: use types that can be encoded in CIC, give a syntactic guard condition that seems plausible, but might have minor bugs that need to be repaired (which is the pragmatic approach to termination taken by Coq). As mentioned before, proving CIC sound was quite a challenge, and I felt it unrealistic to try to prove this target language sound. I also ignored computational relevance for two reasons. First I couldn’t find a great formal description of how to treat <code>Type</code>; there seems to be some kind of static analysis involved in giving it semantics via extraction. Second, after reading a lot about relevance, I think Set vs Prop is sort of the wrong way to encode it anyway, so I’d want to compile those into distinct concepts in the long run. So I decided to do CIC since it’s a more realistic source, but treat soundness of the target and relevance as future work.</p>
<p>To judge this work, we have to look at the type-preserving compilation literature. Since the reviews came out, I’ve been rereading the literature as I work on my thesis proposal, and talking to my committee; this helped put the reviews in a new context for me. The de-facto standard by which we judge type-preserving compilation work is “System F to Typed Assembly Language”. That work does not compile a realistic programming language; it compiles System F. Essentially it shows how to preserve one feature—parametric polymorphism—into a statically typed assembly language. And it took four of the best in our field to do that and do it <em>“right”</em>. While they do not handle a practical source language, they do handle a complicated type theoretic feature, preserve it through a realistic compiler to an assembly like language, and prove type soundness of that target language.</p>
<p>Judged by this standard, I can see the reviewers’ criticism as this: this paper was focusing on the wrong things. I am an academic, not an engineer. Instead of trying to handle all of CIC so that I have a practical source language, I should focus on compiling the new type theoretic feature—full spectrum dependent types—and doing that <em>right</em>. I should carve off the subset that I know how to do well, how to explain well, and how to prove correct. I should leave scaling to all the pragmatic features of CIC as future work, so that I have time to figure out how to do those features <em>right</em>.</p>
<p>So, thank you POPL anonymous reviewers for evaluating my work. You’ve given me a new perspective on my work and I think I know how to improve it.</p>What even is compiler correctness?urn:https-www-williamjbowman-com:-blog-2017-03-24-what-even-is-compiler-correctness2017-03-24T21:41:13Z2017-03-24T21:41:13ZWilliam J. Bowman
<p>In this post I precisely define common compiler correctness properties. Compilers correctness properties are often referred to by vague terms such as “correctness”, “compositional correctness”, “separate compilation”, “secure compilation”, and others. I make these definitions precise and discuss the key differences. I give examples of research papers and projects that develop compilers that satisfy each of these properties.</p>
<!-- more-->
<h3 id="what-is-a-language">What is a Language</h3>
<p>Our goal is to give a generic definition to compiler correctness properties without respect to a particular compiler, language, or class of languages. We first give a generic definition of a Language over which a generic Compiler can be defined.</p>
<p>A Language
<script type="math/tex"> \mathcal{L}</script> is defined as follows.
<script type="math/tex; mode=display">
\newcommand{\peqvsym}{\overset{P}{\simeq}}
\newcommand{\ceqvsym}{\overset{C}{\simeq}}
\newcommand{\leqvsym}{\overset{\gamma}{\simeq}}
\newcommand{\ctxeqvsym}{\overset{ctx}{\simeq}}
\newcommand{\neweqv}[3]{#2 \mathrel{#1} #3}
\newcommand{\peqv}{\neweqv{\peqvsym}}
\newcommand{\ceqv}{\neweqv{\ceqvsym}}
\newcommand{\leqv}{\neweqv{\leqvsym}}
\newcommand{\ctxeqv}{\neweqv{\ctxeqvsym}}
\begin{array}{llcl}
\text{Programs} & P \\
\text{Components} & C \\
\text{Linking Contexts} & \gamma \\
\text{Link Operation} & γ(C) & : & P \\
\text{Program Equivalence} & \peqvsym & : & P \to P \to Prop \\
\text{Linking Equivalence} & \leqvsym & : & \gamma \to \gamma \to Prop \\
\text{Component Equivalence} & \ceqvsym & : & C \to C \to Prop \\
\text{Observational Equivalence} & \ctxeqvsym & : & C \to C \to Prop \\
\end{array}</script> where
<script type="math/tex">\ctxeqvsym</script> is the greatest compatible and adequate equivalence on Components.</p>
<p>A Language
<script type="math/tex">\mathcal{L}</script> has a notion of Programs
<script type="math/tex">P</script>. Programs can be evaluated to produce observations. Program Equivalence
<script type="math/tex">\peqv{P_1}{P_2}</script> defines when two Programs produce the same observations. A Language also has a notion of Components
<script type="math/tex">C</script>. Unlike Programs, Components cannot be evaluated, although they do have a notion of equivalence. However, we can produce a Program from a Component by linking. We Link by applying a Linking Context
<script type="math/tex">\gamma</script> to a Component
<script type="math/tex">C</script>, written
<script type="math/tex">\gamma(C)</script>. Linking Contexts can also be compared for equivalence using Linking Equivalence
<script type="math/tex">\leqv{\gamma_1}{\gamma_2}</script>. Observational Equivalence is a “best” notion of when two Components are related. Note, however, that a Language’s Observational Equivalence is completely determined by other aspects of the language. We are not free to pick this relation.</p>
<p><span class="example">C is a Language; its definition is as follows. Let
<script type="math/tex">P</script> be any well-defined whole C program that defines a function<code>main</code>; such a program would produce a valid executable when compiled. Let
<script type="math/tex">C</script> be any well-defined C program that defines a function<code>main</code>, but requires external libraries to be linked either dynamic or statically. Such a component would produce a valid object file when compiled, but would not run without first being linked. Let
<script type="math/tex">\gamma</script> be directed graphs of C libraries with a C header file. Define the Link Operation by static linking libraries at the C level. Define two Programs to be Program Equivalent when the programs both diverge, both raise the same error, or both terminate leaving the machine in the same state. Define two Linking Contexts to be Equivalent when they are exactly the same. Define two Components to be Component Equivalent when both are Program Equivalent after Linking with Linking Equivalent Linking Contexts.</span></p>
<p><span class="example">Coq (or, CIC) is a Language; its definition is as follows. Let
<script type="math/tex">P</script> be any closed, well-typed Coq expression. Let
<script type="math/tex">C</script> be any open, well-typed Coq expression. Let
<script type="math/tex">\gamma</script> be maps from free variables to Programs of the right type. Define the Link Operation as substitution. Define Components Equivalence and Program Equivalence as definitional equality. Define Linking Equivalence by applying Program Equivalence pointwise to the co-domain of the maps.</span></p>
<h3 id="what-is-a-compiler">What is a Compiler</h3>
<p>Using our generic definition of Language, we define a generic Compiler as follows.</p>
<p>
<script type="math/tex; mode=display">
\newcommand{\newsteqvsym}[1]{_S\!\!#1_T}
\newcommand{\psteqvsym}{\newsteqvsym{\peqvsym}}
\newcommand{\lsteqvsym}{\newsteqvsym{\leqvsym}}
\newcommand{\csteqvsym}{\newsteqvsym{\ceqvsym}}
\newcommand{\psteqv}{\neweqv{\psteqvsym}}
\newcommand{\csteqv}{\neweqv{\csteqvsym}}
\newcommand{\lsteqv}{\neweqv{\lsteqvsym}}
\begin{array}{llcl}
\text{Source Language} & \mathcal{L}_S \\
\text{Target Language} & \mathcal{L}_T \\
\text{Program Translation} & \leadsto & : & P_S \to P_T \\
\text{Component Translation} & \leadsto & : & C_S \to C_T \\
\text{Cross-Language (S/T) Program Equivalence} & \psteqvsym \\
\text{S/T Linking Equivalence} & \lsteqvsym \\
\text{S/T Component Equivalence} & \csteqvsym \\
\end{array}</script></p>
<p>Every Compiler has a source Language
<script type="math/tex">\mathcal{L}_S</script> and target Language
<script type="math/tex">\mathcal{L}_T</script>. We use the subscript
<script type="math/tex">_S</script> when referring to definition from
<script type="math/tex">\mathcal{L}_S</script> and
<script type="math/tex">_T</script> when referring to definitions from
<script type="math/tex">\mathcal{L}_T</script>. Every Compiler defines a translation from
<script type="math/tex">\mathcal{L}_S</script> Programs to
<script type="math/tex">\mathcal{L}_T</script> Programs, and similarly a translation on Components. A Compiler also defines cross-language relations on Programs, Components, and Linking Contexts.</p>
<p><span class="example">We can define a Compiler from C to x86 as follows. Let
<script type="math/tex">\mathcal{L}_S</script> be the Language for C defined earlier. Define a Language for x86 similarly. Let <code>gcc</code> be both the Program and Component Translation. Define S/T Program Equivalence as compiling the Source Language Program to x86, and comparing the machine states after running the x86 programs. Define S/T Linking Equivalence similarly to the definition given for the C Language. Define S/T Component Equivalence by linking with S/T Equivalent Linking Contexts and referring to S/T Program Equivalence.</span></p>
<p><span class="example">We can define a Compiler from Coq to ML as follows. Let
<script type="math/tex">\mathcal{L}_S</script> be the Language for Coq defined earlier. Define a Language for ML similarly. Let the Coq-to-ML extractor be both the Program and Component Translation. Define Program Equivalence via a closed cross-language logical relation indexed by source types. Define Component Equivalence by picking related substitutions, closing the Components, and referring to the Program Equivalence. Define Linking Equivalence by applying Program Equivalence pointwise to the co-domain of the map.</span></p>
<h3 id="what-even-is-compiler-correctness">What Even is Compiler Correctness</h3>
<h4 id="type-preservation">Type Preservation</h4>
<p>The simplest definition of compiler correctness is that we compile Programs to Programs, i.e., our compiler never produces garbage. A slightly less trivial definition is that we compile Components to Components. In the literature, these theorems are called “Type Preservation”. Typically, Type Preservation also connotes that the target language has a non-trivial type system and the compiler is obviously non-trivial.</p>
<p><span class="theorem">Type Preservation (Programs)
<br />
<script type="math/tex"> P_S \leadsto P_T</script></span></p>
<p><span class="theorem">Type Preservation (Components)
<br />
<script type="math/tex">C_S \leadsto C_T</script></span></p>
<p>Type Preservation is only interesting when the source and target languages provide sound type systems that enforces sophisticated high-level abstractions. Even then, it still requires other properties or tests to ensure the compiler is non-trivial. For the user to understand the guarantees of Type Preservation, it is still necessary to understand the target language type system and the compiler.</p>
<p><span class="example">A compiler that compiles every Program to 42 is type-preserving, in the trivial sense. By definition, the source Programs are Programs and 42 is a valid Program in many Languages. However, if you were to call such a compiler “Type Preserving”, the academic community may laugh at you.</span></p>
<p><span class="example">A C-to-x86 compiler is type-preserving, in the trivial sense. Neither C nor x86 provide static guarantees worth mentioning. If you were to call such a compiler “Type Preserving”, the academic community may laugh at you.</span></p>
<p><span class="example">The <a href="http://compcert.inria.fr/">CompCert</a> C-to-Mach is type-preserving, in a weak but non-trivial sense. CompCert enforces a particular memory model and notion of memory safety, and preserves this specification through the compiler to a low-level machine independent language called Mach. The assembler is type-preserving in a trivial since, since x86 provides no static guarantees to speak of.</span></p>
<p><span class="example">The Coq-to-ML extractor is type-preserving, in a pretty trivial sense. As ML has a less expressive type system than Coq, and the extractor often makes use of casts, Type Preservation provides few guarantees for Components. For example, it is possible to cause a segfault by linking a extracted ML program a with a stateful ML program.</span></p>
<p><span class="example">The <a href="https://www.cs.princeton.edu/~dpw/papers/tal-toplas.pdf">System F-to-TAL</a> compiler is type-preserving in a strong sense. System F provides strong data hiding and security guarantees via parametric polymorphism. TAL provides parametric polymorphic and memory safety, allowing all of System F’s types to be preserved. Even so, type preservation could hold if we compile everything to the trivial TAL program, such as <code>halt[int]</code>. However, a quick look at the definition of the compiler or a small test suite is sufficient to convince us that the compiler is non-trivial, and thus Type Preservation is meaningful in this context.</span></p>
<h4 id="whole-program-correctness">Whole-Program Correctness</h4>
<p>The next definition is what I would intuitively expect of all compilers (that are bug free). A source Program should be compiled to a “related” target Program. In the literature, this theorem is referred to as “Whole-Program Correctness” or “Semantics Preservation”. Note that any Whole-Program or Semantics Preserving Compiler is also trivially Type Preserving. Such as Compiler may also be Type Preserving in a non-trivial sense.</p>
<p><span class="theorem">Whole-Program Correctness
<br /> If
<script type="math/tex">P_S \leadsto P_T</script> then
<script type="math/tex">\psteqv{P_S}{P_T}</script></span></p>
<p>A whole-program compiler provides no guarantees if we attempt to compile a Component and then link. Since many, arguably all, Programs are actually Components, Whole-Program Correctness is of limited use. A notable exception is in the domain embedded systems. In this domain, writing a whole source program may be practical.</p>
<p><span class="example">The <a href="http://compcert.inria.fr/">CompCert</a> C-to-Asm compiler is proven correct with respect to Whole-Program Correctness, with machine checked proofs. CompCert refers to this guarantee as “semantics preservation”. Prior versions of CompCert pointed out that, while it is possible to Link after compilation, “the formal guarantees of semantic preservation apply only to whole programs that have been compiled as a whole by CompCert C.” More recent versions lift this restrctions, as we discuss shortly.</span></p>
<p><span class="example">The <a href="https://cakeml.org/">CakeML</a> CakeML-to-Asm compiler is proven correct with respect to Whole-Program Correctness, with machine checked proofs. CakeML is “a substantial subset of SML”. Asm is one of several machine languages: ARMv6, ARMv8, x86–64, MIPS–64, and RISC-V. The assemblers here, unlike in <a href="http://compcert.inria.fr/">CompCert</a>, are proven correct.</span></p>
<h4 id="compositional-correctness">Compositional Correctness</h4>
<p>Intuitively, Compositional Correctness is the next step from Whole-Program Correctness. Compositional Correctness should give us guarantees when we can compile a Component, then Link with a valid Linking Context in the target Language.</p>
<p><span class="theorem">Compositional Correctness
<br /> If
<script type="math/tex">C_S \leadsto C_T</script> and
<script type="math/tex">\lsteqv{\gamma_S}{\gamma_T}</script> then
<script type="math/tex">\psteqv{\gamma_S(C_S)}{\gamma_T(C_T)}</script></span></p>
<p>To understand the guarantees of this theorem, it is necessary to understand how Linking Contexts are related between the source and target Languages. For instance, some compilers may allow linking with arbitrary target Linking Contexts. Some compilers may restrict linking to only Linking Contexts produced by the compiler.</p>
<p>The phrase “Compositional Correctness” usually connotes that the relation
<script type="math/tex">\lsteqvsym</script> is defined independently of the compiler—that is, it is used to mean there is a specification separate from the compiler for cross-language equivalent Linking Contexts. This supports more interoperability, since linking is permitted even with Linking Contexts produced from other compilers, or handwritten in the target language, as long as they can be related to source Linking Contexts.</p>
<p><span class="theorem">Compositional Compiler Correctness
<br /> If
<script type="math/tex">C_S \leadsto C_T</script> and
<script type="math/tex">\lsteqv{\gamma_S}{\gamma_T}</script> then
<script type="math/tex">\psteqv{\gamma_S(C_S)}{\gamma_T(C_T)}</script> (where
<script type="math/tex">\lsteqvsym</script> is independent of
<script type="math/tex">\leadsto</script>)</span></p>
<p>The phrase “Separate Compilation” usually connotes that linking is only defined with Linking Contexts produced by same compiler. That is, when
<script type="math/tex">\lsteqv{\gamma_S}{\gamma_T} \iff \gamma_S \leadsto \gamma_T</script>.</p>
<p><span class="theorem">Correctness of Separate Compilation
<br /> If
<script type="math/tex">C_S \leadsto C_T</script> and
<script type="math/tex">\gamma_S \leadsto \gamma_T</script> then
<script type="math/tex">\psteqv{\gamma_S(C_S)}{\gamma_T(C_T)}</script></span></p>
<p>Some papers present a variant of “Semantics Preservation” stated of Components instead of Programs. Usually, this theorem implies Compositional Correctness. This require a cross-language equivalence on Components, which is usually defined in terms of linking with S/T Equivalent Linking Contexts and observing S/T Equivalent Programs.</p>
<p><span class="theorem">Semantics Preservation
<br /> If
<script type="math/tex">C_S \leadsto C_T</script> then
<script type="math/tex">\csteqv{C_S}{C_T}</script></span></p>
<p>Some papers define interoperability between source Components and target Linking Contexts, and between target Components and source Linking Contexts. This supports a broader notion of linking and thus a more widely applicable Compositional Correctness guarantee. However, it requires understanding the source/target interoperability semantics to understand the guarantee. There is no way to relate the resulting behaviors back to the source language, in general.</p>
<div class="theorem">Open Compiler Correctness
<br />
<ol>
<li>If
<script type="math/tex">C_S \leadsto C_T</script>, then for all
<script type="math/tex">\gamma_T</script>,
<script type="math/tex">\psteqv{\gamma_T(C_S)}{\gamma_T(C_T)}</script></li>
<li>If
<script type="math/tex">C_S \leadsto C_T</script>, then for all
<script type="math/tex">\gamma_S</script>,
<script type="math/tex">\psteqv{\gamma_S(C_S)}{\gamma_S(C_T)}</script></li></ol></div>
<p>Note that to satisfy Open Compiler Correctness, two new definitions of linking must be defined: one that links target Linking Contexts with source Components, and one that links source Linking Contexts with target Components.</p>
<p>Most compilers that generate machine code aim to be Compositional Compilers, since we should be able to link the output with any assembly, even that produced by another compiler. Compilers that target .NET VM, JVM, and LLVM are similar.</p>
<p>Some languages, like Coq and Racket, target special purpose VMs and aim only to be Separate Compilers.</p>
<p>Languages with FFIs can be thought to aim for a limited form of Open Compiler Correctness. For instance, we can link Java and C code for certain limited definitions of Linking Contexts. The full spirit of the theorem is limited to research projects, for now.</p>
<p><span class="example">The <a href="https://www.cs.princeton.edu/~appel/papers/compcomp.pdf">Compositional CompCert</a> compiler extends <a href="http://compcert.inria.fr/">CompCert</a> and its correctness proofs to guarantee Compositional Compiler Correctness. Linking is defined for any target Linking Context whose <em>interaction semantics</em> are related to a source Linking Context. The paper’s Corollary 2 titled “Compositional Compiler Correctness” is a generalized version of our theorem by the same name. They allow for compiling an arbitrary number of Components, then linking those with a Linking Context.</span></p>
<p><span class="example">The <a href="https://people.mpi-sws.org/~viktor/papers/sepcompcert.pdf">SepCompCert</a> compiler extends <a href="http://compcert.inria.fr/">CompCert</a> and its correctness proofs to guarantee Separate Compiler Correctness. This work notes that Separate Compiler Correctness is significantly easier to proof, increasing the proof size by 2%, compared to the 200% required in Compositional CompCert. This work was merged into CompCert as of <a href="https://github.com/AbsInt/CompCert/releases/tag/v2.7">version 2.7</a>.</span></p>
<p><span class="example">The <a href="http://plv.mpi-sws.org/pils/paper.pdf">Pilsner</a> compiler is an MLish-to-Assemblyish compiler that guarantees Compositional Compiler Correctness. Linking is defined for any target Linking Context that is related to a MLish Component by a PILS.</span></p>
<p><span class="example"><a href="http://www.ccs.neu.edu/home/amal/papers/voc.pdf">Perconti and Ahmed</a> develop a compiler from System F to a low-level typed IR that guarantees Open Compiler Correctness. In every Language, Linking is defined for any Linking Context in the source, intermediate, or target languages that has a compatible type. This paper defined a multi-language semantics in which all languages can interoperate.</span></p>
<h4 id="equivalence-preservation">Equivalence Preservation</h4>
<p>Some properties of a program cannot be stated in terms of a single run of the program. We require more sophisticated compiler correctness theorems to show these properties are preserved. For instance, security properties, such as indistinguishably of a cipher text to a random string, are relational properties. These can only be stated as a property between two Programs in the same Language.</p>
<p>Equivalence Preserving, or Fully Abstract compilers, seek to prove compilers preserve these relational properties. Since security properties are often relational, these are sometimes called “Secure Compilers”. Often times, we also want to <em>reflect</em> equivalence, which usually follows from Compositional Correctness. Full Abstraction refers specifically to preserving and reflecting Observational Equivalence.</p>
<p>Compilers that guarantee these properties are limited to research projects, as there are many open problems to be solved. The key difficulty lies in the proofs of Equivalence Preservation, which essentially requires “decompiling” a target Program into a source Program.</p>
<p><span class="theorem">Equivalence Preservation
<br /> If
<script type="math/tex">\ceqv{C_S}{C'_S}</script> and
<script type="math/tex">C_S \leadsto C_T</script> and
<script type="math/tex">C'_S \leadsto C'_T</script> then
<script type="math/tex">\ceqv{C_T}{C'_T}</script></span></p>
<p><span class="theorem">Equivalence Reflection
<br /> If
<script type="math/tex">\ceqv{C_T}{C'_T}</script> and
<script type="math/tex">C_S \leadsto C_T</script> and
<script type="math/tex">C'_S \leadsto C'_T</script> then
<script type="math/tex">\ceqv{C_S}{C'_S}</script></span></p>
<p><span class="theorem">Full Abstraction
<br /> Let
<script type="math/tex">C_S \leadsto C_T</script> and
<script type="math/tex">C'_S \leadsto C'_T</script>.
<script type="math/tex">\ctxeqv{C_S}{C'_S}</script> iff
<script type="math/tex">\ctxeqv{C_T}{C'_T}</script></span></p>
<p><span class="example"><a href="https://williamjbowman.com/papers/#niforfree">Bowman and Ahmed</a> develop an Equivalence Preserving and Reflecting compiler from The Core Calculus of Dependency (DCC) to System F. DCC guarantees certain security properties, which are preserved by encoding using parametric polymorphism. This compiler also satisfies Compositional Compiler Correctness, using a cross-language logical relation to define relatedness of Components between languages. This compiler is not Fully Abstract, as it does not define Contextual Equivalence. Instead, the compiler Preserves and Reflects the security property of interest.</span></p>
<p><span class="example"><a href="https://www.microsoft.com/en-us/research/wp-content/uploads/2013/01/js-star.pdf">Fournet et al.</a> develop a Fully Abstract compiler from a language similar to a monomorphic subset of ML with exceptions to JavaScript. This paper demonstrates a key difficulty in Fully Abstract compilers. Often, the source language must be artificially constrained (in this case, by eliminating polymorphism and adding exceptions) in order to support back-translation.</span></p>
<p><span class="example"><a href="https://people.mpi-sws.org/~marcopat/marcopat/Publications_files/logrel-for-facomp.pdf">Devriese et al.</a> develop a Fully Abstract compiler from STLC to the untyped lambda calculus. This paper developed a key innovation in back-translation techniques, allowing a more expressive and less typed target language to be back-translated to a less expressive source and more typed source language.</span></p>Toward Type-Preserving Compilation of Coq, at POPL17 SRCurn:https-www-williamjbowman-com:-blog-2017-01-03-toward-type-preserving-compilation-of-coq-at-popl17-src2017-01-03T21:41:11Z2017-01-03T21:41:11ZWilliam J. Bowman
<p>Almost two months ago, my colleagues in the Northeastern PRL wrote about <a href="http://prl.ccs.neu.edu/blog/2016/11/17/src-submissions/">three of our POPL 2017 Student Research Competition submissions</a>. There was fourth submission, but because I was hard at work completing proofs, it wasn’t announced.</p>
<h2 id="toward-type-preserving-compilation-of-coq">Toward Type-Preserving Compilation of Coq</h2>
<p><a href="https://williamjbowman.com/papers#cccc-popl17-src">Toward Type-Preserving Compilation of Coq</a>
<br /> William J. Bowman
<br /> 2016
<br /></p>
<blockquote>
<p>A type-preserving compiler guarantees that a well-typed source program is compiled to a well-typed target program. Type-preserving compilation can support correctness guarantees about compilers, and optimizations in compiler intermediate languages (ILs). For instance, <a href="http://dx.doi.org/10.1145/268946.268954">Morrisett <em>et al.</em> (1998)</a> use type-preserving compilation from System F to a Typed Assembly Languages (TAL) to guarantee absence of stuckness, even when linking with arbitrary (well-typed) TAL code. <a href="http://doi.acm.org/10.1145/231379.231414">Tarditi <em>et al.</em> (1996)</a> develop a compiler for ML that uses a typed IL for optimizations.</p>
<p>We develop type-preserving closure conversion for the Calculus of Constructions (CC). Typed closure conversion has been studied for simply-typed languages (<a href="http://dx.doi.org/10.1145/237721.237791">Minamide1996</a>, <a href="https://dl.acm.org/citation.cfm?id=1411227">Ahmed2008</a>, <a href="http://doi.acm.org/10.1145/2951913.2951941">New2016</a>) and polymorphic languages (<a href="http://dx.doi.org/10.1145/237721.237791">Minamide1996</a>, <a href="http://dx.doi.org/10.1145/268946.268954">Morrisett1998</a>). Dependent types introduce new challenges to both typed closure conversion in particular and to type preservation proofs in general.</p></blockquote>ICFP 2016urn:https-www-williamjbowman-com:-blog-2016-10-15-icfp-20162016-10-15T21:15:00Z2016-10-15T21:15:00ZWilliam J. Bowman
<p>Full disclosure: This blog post is sponsored in part by ACM SIGPLAN. ACM SIGPLAN! Pushing the envelope of language abstractions for making programs better, faster, correcter, stronger.</p>
<h4 id="tldr">TLDR</h4>
<p>I went to ICFP again this year. I’m a frequent attendee. Last year I had <a href="/papers/#niforfree">a paper</a> and <a href="https://youtu.be/-vgWefEXHt0">gave a talk</a>. This year I had <a href="/papers/#fabcc">a paper</a>, but someone else gave <a href="https://www.youtube.com/watch?v=Hylji4ezQHE">the talk</a>. But I also gave a <a href="http://conf.researchr.org/event/hope-2016/hope-2016-papers-growing-a-proof-assistant">talk</a> at HOPE 2016. I met some people and saw some talks and pet a deer.</p>
<hr />
<!-- more-->
<p>I’m a fifth year Ph.D. candidate studying compiler correctness, dependent types, and (functional) programming language abstractions. ICFP is my second home.</p>
<p>This year, I met some cool new researchers, several of whose names I’ve already forgotten (sorry new friends). I met <a href="https://zoep.github.io/">Zoe Paraskevopoulou</a>, who works on the CertiCoq project, a combination of my two favorite things: compiler correctness and dependent types. We talked a bit about this because I too have been looking at correctly compiling dependent types. I also met <a href="http://pleiad.cl/people/etanter">Éric Tanter</a>, who works on, among many things, gradual typing and dependent types. He gave <a href="https://youtu.be/GwmZTGd1rZs">a talk</a> on a method for verified interoperability with dependent types, which is related to certain kinds of compiler correctness problems that interest me, such as compositional compiler correctness and full abstraction. He’s also interested in Racket, so we spent some time discussing <a href="/papers/#cur">Cur</a>.</p>
<p>I got some new ideas for Cur. <a href="http://davidchristiansen.dk/">David Christiansen</a>’s talk on <a href="https://youtu.be/pqFgYCdiYz4">Elaborator Reflection: Extending Idris in Idris</a> did a great job of motivating the problem and comparing meta-programming styles in proof assistants. The elaborator monad looks like a good abstraction for reasoning about certain kinds of extensions, and I need to figure out how to make it good for reasoning about the complex extensions possible in Cur. <a href="https://distrinet.cs.kuleuven.be/people/jesper">Jesper Cockx</a>’s talk on <a href="https://youtu.be/TbyAfTCbyHQ">Unifiers as Equivalences</a> demonstrated ideas that might let me implement unification as a user defined extension in a proof-relevant way.</p>
<p>I saw most of the other talk, and a bunch of talks at the workshops. I have pages and pages of notes, and dozens of items in my TODO list to go and review papers and talks that I didn’t properly digest the first time. I hope I finish those by next year.</p>Post-ECOOPurn:https-www-williamjbowman-com:-blog-2016-08-10-post-ecoop2016-08-10T19:46:50Z2016-08-10T19:46:50ZWilliam J. Bowman
<p>I returned from ECOOP a few weeks ago, and have been trying to figure out what I got of the experience. I’ll focus on two big things.</p>
<p>For a long time I have been debating what I should do after I graduate, which I usually phrase as “industry vs academia”. I’m coming to understand this is a false dichotomy, as most dichotomies are. (It helps that a friend <a href="https://twitter.com/chckadee/status/761312153370517504">spelled it out for me</a>.) Dave Herman’s talk, on starting and running a research lab doing academic-style work (e.g., developing a principled, safe programming language) in industry, helped me see that. Shriram’s summer school lectures were equally helpful, and sort of the dual of this: taking objects from industry—scripting languages—and applying academic rigor to them. ECOOP, more than any other conference I’ve been to, brought together industry and academia in a smooth spectrum. I wish I had attended as a younger student.</p>
<p>The other big thing was a crystallized version of thoughts I had on programming language. Matthias Felleisen on Racket and Larry Wall on Perl 6 helped me see this: anything you might want to do to or in a program should be expressible in your programming language (Matthias said it better). This is what annoys me about languages like C, Java, and Coq. C has the preprocessor and <code>make</code> and the dynamic linker, etc. Java has Eclipse. Coq has OCaml plugins. All of these languages require doing “more” than writing programs, but have no way to express it in the language. Racket (and, apparently, Perl 6) pulls those things into the language so that those too become just writing programs: extend the reader, dynamically load a library, muck about with the top level, add new syntax.</p>
<p>I got a handful of smaller things: insights about what objects are best at, what a long-term (~25 year) research agenda looks like, an appreciation for the 99 different designs for any given program.</p>
<p>ECOOP was a great experience. If I go again, though, I hope the summer school won’t conflict with the entire research track.</p>ECOOP 2016urn:https-www-williamjbowman-com:-blog-2016-07-15-ecoop-20162016-07-15T20:18:06Z2016-07-15T20:18:06ZWilliam J. Bowman
<p>Full disclosure: This blog post is sponsored and required by the National Science Foundation (NSF): The NSF! Funding SCIENCE! since 1683 or whenever.</p>
<h4 id="tldr">TLDR</h4>
<p>I’m going to ECOOP to see a part of the PL community I wouldn’t normally see, talk to people that I wouldn’t normally talk to, attend the co-located summer school, and figure out what I want to do with my (academic) life. If you want to know why I might do those things, <a href="https://williamjbowman.com">read a little about me</a>.</p>
<h4 id="the-long-story">The long story</h4>
<p>On Sunday, I am heading to ECOOP. I have never been to ECOOP, the conference is a little outside of my specialty, I do not know anyone there, and I do not even have a paper or talk at one of the workshops. However, a few weeks ago I ignored an email from one of the mailing lists that said there was some NSF funding that students should apply for. Then I saw an email from Jan Vitek on a local mailing list saying students should really apply for this funding and get to go to Rome.</p>
<p>“Huh”, I thought to myself, “I wonder what’s interesting in Rome”. I went to the <a href="http://2016.ecoop.org/program/program-ecoop-2016">ECOOP program</a> and started looking around.</p>
<p>The Curry On program looks interesting. This co-located conference should help me understand how PL applies to industry problems. Unfortunately, I’m going to miss most or all the first day. But the talk I’m most interested in is the final keynote, “Building an Open Source Research Lab”; hopefully this will give me some insights on this <a href="https://williamjbowman.com/blog/2015/11/02/to-academia-or-not-to-academia">industry vs academia problem I have been struggling with</a>.</p>
<p>There is also a summer school. While the history of typed and untyped languages looks fascinating, I’m going to have to skip part of it to learn about type specialization of JavaScript programs; I prove things on type-preserving compilation and I want to see more work that uses types for optimizations. Next up, the lecture on “Building a Research Program for Scripting Languages” should help me better understand what an academic career will look like, and give me some idea of how to be a good academic. Then I’m going to learn how to build a JIT compiler for free, because despite being a compilers expert, I don’t know anything about JIT compilers. Finally, I’m going to learn a little about experimental evaluation; I normally do theory and proofs, but I imagine one day I might need to measure something.</p>
<p>Unfortunately, the summer school is in parallel with most of the conference talks, so it’s going to be tough to decide how much of the summer school to miss in order to see new research.</p>
<p>“Yeah”, I thought after much consideration, “I guess there are some interesting things to see in Rome”. I’m a little concerned about the accommodations and venue though; I understand that a lot of the architecture in Rome is <em>very</em> old.</p>Conference talks reconsideredurn:https-www-williamjbowman-com:-blog-2015-08-29-conference-talks-reconsidered2015-08-30T04:18:36Z2015-08-30T04:18:36ZWilliam J. Bowman
<p>A couple weeks ago, I wrote that I was beginning to hate conference talks. The next morning, I woke up with 50+ Twitter notifications caused by people debating that point. I have reconsidered my views.</p>
<p>In my earlier post, I point out that the typical advice I hear is “The talk should be an ad for the paper”. After several discussions, I think this is bad advice. Instead, <a href="http://composition.al/">Lindsey Kuper</a> and <a href="https://www.cs.cmu.edu/~cmartens/">Chris Martens</a> encouraged me to ignore this advice and instead make my talk a performance.</p>
<p>At first, I was unsure what this meant. In fact, I am still not quite what this means. What does it mean to perform a paper? But I followed it anyway.</p>
<p>Essentially I tried to communicate, at a high-level, why I think this work is cool, and what parts of the work are most interesting. I tried to tell a story about what inspired this work, why I care about it, and what came out of it. I did not try to show many technical details; I showed only those necessary to tell the story of this work. I did not try to explain the particulars of all this work; I showed only those necessary to fit the work into the context of the story I wanted to tell.</p>
<p>I think the end result is actually an effective ad for the paper. However, by approaching the talk differently, I produced a much better talk (IMHO). And thankfully, I am not alone in that opinion. For example, I was very excited after my initial practice talk when Matthias called the talk “90% perfect”, in defiance of a NU PRL tradition of not dwelling on positive aspects and only giving constructive <em>criticism</em> after a practice talk.</p>
<p>A video of this talk is <a href="https://youtu.be/-vgWefEXHt0">online here</a>.</p>Conference talksurn:https-www-williamjbowman-com:-blog-2015-08-08-conference-talks2015-08-08T22:24:06Z2015-08-08T22:24:06ZWilliam J. Bowman
<p>I am beginning to hate conference talks. I am in the midst of writing a conference talk for my <a href="/papers#niforfree">recently accepted paper</a>. Although I have only given one conference talk thus far, I have attended several conference and listened to many talks. These experiences have convinced me that conference talks are largely pointless.</p>
<p>I do not find conferences to be pointless. The papers are usually well written, if dense. The conferences themselves always lead to interesting conversations with clever people. I always return from a conference filled with creative energy. And, I admit, I like the excuse to travel to interesting locales.</p>
<p>However, the talks themselves are pointless. Most talks I have attended are terrible. Those that are not terrible I do not remember much of anyway, except that I should go read that paper. Of those talks, I would have made the same decision after reading the abstract for the paper. The talks add nothing because the talk slots are too short to communicate any technical material.</p>
<p>It is not entirely the fault of the speakers. For one, there is little incentive to give a good talk. If you give a good talk, then maybe you convince someone to read your paper, and maybe people remember who you are. This might be important if you are on the job market, but it does not matter for everyone else. Besides, most people will forget the talk in a month, good or bad.</p>
<p>Even if you are a perfectionist so incentive does not matter, it is not easy to craft a good talk. Conference papers are often complex and dense pieces of work. Frequently, the papers omit many details due to space, so completely understanding the work requires not only the paper but a technical appendix or code artifact published separately. Authors (usually (maybe only sometimes)) spend a great deal of time polishing these papers and supplementary materials to effectively communicate a complex and dense piece of work. The slot for the conference talk is 15—20 minutes, in which a speaker much fit a 12-page paper plus supplementary material?</p>
<p>“No! Obviously as a speaker you must <em>not</em> do that. The talk should be an advertisement for the paper. It should be an overview of the paper. It should communicate the key technical ideas and convince people to read the paper.”</p>
<p>What silly advice. I hate advertisements. Why should I sit through sessions and sessions of advertisements?</p>
<p>“No! Obviously as an audience member you must <em>not</em> do that. Just go read the abstracts and find the talks you want to attend. Skip the rest to have conversations with colleagues and authors.”</p>
<p>Okay, so the audience is going to read the abstract to convince them to see a talk that convinces them to read the paper of which they just read the to convince them to see the talk that convinces them to read the paper? This is circular reasoning that wastes the time of both the speaker and the audience.</p>
<p>As a speaker and writer, I have already spent a lot of time and effort on the paper. I have crafted the abstract and introduction to communicate the key technical ideas and give an overview of the paper as precisely and concisely as possible. Shortly thereafter, I have carefully written the rest of the paper to effectively communicate the technical contributions in as much detail yet as concisely as page limits allow. Besides, I had to write them anyway to effectively communicate my research. Why should I reproduce these efforts in a short talk that must communicate less due to the nature of the talk and the audience?</p>
<p>As an audience member, if I want an overview of the paper, the abstract and introduction section provide this. The author already spent a great deal of time writing these sections, which communicate more thoughts in less time than the talk will. If I want more details, these sections are conveniently located with the rest of the paper. Besides, I need to read the abstract anyway to figure out which talks to attend and which papers to read. Why should I then sit through a talk that advertises a paper that I have already decided whether or not to read?</p>
<p>“Well the talks give an excuse and talking points around which we can organize a conference.”</p>
<p>Well why can’t we find a better excuse or better talking points? Why not give longer highly-technical talks that supplement the paper, or questions-and-answer style talks for those who have read the paper and want more? Or why not make the papers more open ended so talks can be more speculative?</p>
<p>I do not know what should go in place of the current conference talks, but the current system seems utterly pointless and results in completely wasted effort.</p>Notes on "Ur: Statically-Typed Metaprogramming ..."urn:https-www-williamjbowman-com:-blog-2015-02-14-notes-on-ur-statically-typed-metaprogramming2015-02-14T17:22:11Z2015-02-14T17:22:11ZWilliam J. Bowman
<p>Today I read <a href="http://adam.chlipala.net/papers/UrPLDI10/">Ur: Statically-Typed Metaprogramming with Type-level Record Computation</a>. This paper presents the Ur language, a functional programming language based on an extension of System Fω. The novel idea is to use type-level functions as a form of type-safe meta-programming. The paper claims this novel idea enables safe heterogeneous and homogeneous meta-programming in Ur.</p>
<p>The interesting insight is that type-level computation may be valuable outside of dependently typed languages. The paper quickly and easily makes this case. The type-level computations reduce type annotations by enabling the programmer to compute types rather than manually write them everywhere. This could be a useful form of meta-programming in any typed language.</p>
<p>The claims about heterogeneous and homogeneous meta-programming seem overstated. Ignoring the novel ability to compute type annotations, type-safe heterogeneous programming could be as easily accomplished in any other type-safe language. I could just as easily (or more easily) write a program in Coq, ML, Haskell, or Typed Racket that generates HTML and SQL queries as I could in Ur. As for homogeneous meta-programming, restricting the meta-programs to record computations at the type-level seems to severely restricts the ability to generate code at compile-time and abstract over syntax, features which are provided by general-purpose meta-programming systems such as Racket’s macros or Template Haskell.</p>Beluga and explicit contextsurn:https-www-williamjbowman-com:-blog-2014-09-10-beluga-and-explicit-contexts2014-09-11T00:56:44Z2014-09-11T00:56:44ZWilliam J. Bowman
<p>In my recent work, I found it useful to pair a term and its context in order to more easily reason about weakening the context. At the prompting of a colleague, I’ve been reading about Beluga, <a href="http://www.cs.mcgill.ca/~complogic/beluga/flops10/flops.pdf" title="Beluga: programming with dependent types, contextual data, and
contexts">[1]</a> <a href="http://www.cs.mcgill.ca/~bpientka/papers/ppdp-pientka.pdf" title="Programming with Proofs and Explicit Contexts">[2]</a>, and their support for programming with explicit contexts. The idea seems neat, but I’m not quite sure I understand the motivations or implications.</p>
<p>So it seems Beluga has support for describing what a context contains (schemas), describing in which context a type/term is valid, and referring to the variables in a context by name without explicitly worrying about alpha-renaming. This technique supports reasoning about binders with HOAS in more settings, such as in the presence of open data and dependent types. Since HOAS simplifies reasoning about binders by taking advantage of the underlying language’s implementation of substitutions, this can greatly simplify formalized meta-theory in the presence of advanced features which previously required formalizing binders using more complicated techniques like De Bruijn indices. By including weakening, meta-variables, and parameter variables, Beluga enables meta-theory proofs involving binders to be much more natural, i.e., closer to pen-and-paper proofs.</p>
<p>Obviously this is great for formalized meta-theory. While I have seen how HOAS can simplify life for the meta-theorist, and seen how it fails, I don’t fully understand the strengths and weakness of this work, or how it compares to techniques such as the <a href="http://www.chargueraud.org/softs/ln/" title="LN: Locally nameless representation">locally nameless</a>. I’m also not sure if there is more to this work than a better way to handle formalization of binding (which is a fine, useful accomplishment by itself).</p>
<p>If anyone can elaborate on or correct my understanding, please do.</p>FASTRurn:https-www-williamjbowman-com:-blog-2013-03-13-fastr2013-03-13T07:05:00Z2013-03-13T07:05:00ZWilliam J. Bowman
<p>FASTR is a bill to ensure all publically funded research is open access. I urge you all to contact your congresspeople and demand they support this bill.</p>
<!-- more-->
<p>If you need help, <a href="https://action.eff.org/o/9042/p/dia/action/public/?action_KEY=9061">the EFF has a page</a> from which you can contact your congresspeople. You can use their template, or my template below that has been customized for researchers.</p>
<blockquote>
<p>As your constituent, and as a university researcher, I am urging you to support the Fair Access to Science & Technology Research Act (FASTR is S. 350 in the Senate and H.R. 708 in the House).</p>
<p>As a researcher, I want my research distributed widely, to anyone who is willing to read it! We in the scientific community are often held to the whims of for-profit journals and publishing agents—agents we must publish through to advance our career, and to get our work seen in the field, due the monopoly-like grip they have on what constitutes a high quality publishing venue—who seek to maximize profit at the expense of taxpayer dollars and the advancement of knowledge.</p>
<p>This research is developed, written, reviewed, digitally typeset, and presented AT NO COST to these publisher, BY US RESEARCHERS, who are often funded with taxpayer dollars through public universities and government agencies like the National Science Foundation. Some venues, through obscene application of copyright, do not allow authors to provide digital copies of THEIR OWN WORK via their personal websites or other means of distribution.</p>
<p>As a result, students, researchers at less well-funded institutions, and citizens have difficulty accessing information they need; professors have a harder time reviewing and teaching the state of the art; cutting-edge research remains hidden.</p>
<p>FASTR helps fix this. The bill makes government agencies design and implement a plan to facilitate public access to the results of their investments. Any researcher who receives federal funding must submit a copy of resulting journal articles to the funding agency, which will then make that research widely available within six months.</p>
<p>Please secure our rights as taxpayers, and our rights as scientists, and promote the progress of science by supporting FASTR.</p></blockquote>