<?xml version="1.0" encoding="utf-8"?> 
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
 <title type="text">λk.(k blog): Posts tagged 'research'</title>
 <link rel="self" href="https://www.williamjbowman.com/feeds/research.atom.xml" />
 <link href="https://www.williamjbowman.com/tags/research.html" />
 <id>urn:https-www-williamjbowman-com:-tags-research-html</id>
 <updated>2026-03-25T00:26:51Z</updated>
 <entry>
  <title type="text">Please don't generate your bibliography</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2026/03/24/please-don-t-generate-your-bibliography/" />
  <id>urn:https-www-williamjbowman-com:-blog-2026-03-24-please-don-t-generate-your-bibliography</id>
  <published>2026-03-25T00:26:51Z</published>
  <updated>2026-03-25T00:26:51Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;I read a lot of bibliographies. I also read a lot of bad bibliographies, most of which are clearly autogenerated. I don&amp;rsquo;t like reading bad bibliographies.&lt;/p&gt;

&lt;p&gt;There are two purposes to a bibliography.&lt;/p&gt;

&lt;p&gt;The first is to communicate which article is being cited to the reader. For that, it’s important to make the citation information very clear and consistent.&lt;/p&gt;

&lt;p&gt;The second is to make it possible for the reader to find the thing being cited. For that, you need as much information as necessary to track down the original article. If you have a DOI, that becomes pretty trivial, so most other information can be excluded. If you don’t have a DOI, you may need to call a librarian and they may need lots of specific information. If you haven&amp;rsquo;t had to do this, go find an old paper in your field and try to track down a physical copy. It&amp;rsquo;s a learning experience.&lt;/p&gt;

&lt;p&gt;I have a style guide and some rules-of-thumb I use to try to satisfy these two goals:&lt;/p&gt;

&lt;p&gt;For provenance:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;For all citations, include DOIs, or URLs from the most authoritative, least-likely to fail/change institution if no DOIs available.&lt;/li&gt;
 &lt;li&gt;If no DOI/URL is available, include as much citation information as possible.&lt;/li&gt;
 &lt;li&gt;When DOIs and canonical URLs are available, avoid including things like publisher names and addresses, editor names, etc. This is just clutter.&lt;/li&gt;
 &lt;li&gt;If a URL of dubious longevity is the only available, try to archive it with &lt;a href="https://web.archive.org/"&gt;https://web.archive.org/&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;For clarity:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Never use automatically generated bib information; always clean it up and try to keep consistent.
  &lt;ul&gt;
   &lt;li&gt;I always manually replace the conference name with something more legible. The autogenerated one will often also contain the venue location, the date, the venue’s iteration number. I exclude all that, since most of that is elsewhere in the bib or is irrelevant. You can use bibtex string constants to make this easy.&lt;/li&gt;
   &lt;li&gt;I exclude the ACM SIGPLAN nonsense for the most well-known venues.&lt;/li&gt;
   &lt;li&gt;I typically exclude editors, which don’t really matter&lt;/li&gt;
   &lt;li&gt;I typically exclude page number, except for journal articles&lt;/li&gt;
   &lt;li&gt;I typically exclude the publisher, unless there is no DOI or URL. The publisher is useful if you need to track down a copy of the article, but if you have a DOI or authoritative URL, the publisher shouldn’t be necessary.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
 &lt;li&gt;Avoid duplicate DOIs + URL.&lt;/li&gt;
 &lt;li&gt;Use braces {} to guard any word in titles that need capitalization, such as {AI} or {CIC}.&lt;/li&gt;
 &lt;li&gt;Never use the SIGPLAN Notices version of a citation. Some versions of ICFP, POPL, etc, papers were also published as &amp;ldquo;SIGPLAN Notices&amp;rdquo; journal articles. This can confuse readers. The two versions are the same paper, but have different DOIs and citation information. Make sure to find the conference version, and not the SIGPLAN Notices version. For example, see these two citations:
  &lt;ul&gt;
   &lt;li&gt;&lt;a href="https://dl.acm.org/doi/10.1145/3093333.3009886"&gt;https://dl.acm.org/doi/10.1145/3093333.3009886&lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;&lt;a href="https://dl.acm.org/doi/10.1145/3009837.3009886"&gt;https://dl.acm.org/doi/10.1145/3009837.3009886&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;To implement these rules, I use Jabref.  It can pull in the autogenerated information, then I manually clean it up according to my rules. Jabref supports marking fields as optional or required depending on the type, so I usually just delete all the optional fields, unless there&amp;rsquo;s not DOI. I use lots of bibtex string constants for common venues, to help clean up the bibtex and keep things consistent.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s always disappointing to me when I read a completely autogenerated bibliography. It&amp;rsquo;s obvious; it looks like slop, and accomplishes neither of the two goals of a bibliography. I was just reading one, and no entry had a DOI at all, titles had incorrect capitalization all over the place, many of the proceedings included cities and dates duplicated in the date field.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">Against Vibes: When is a Generative Model Useful</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2026/03/05/against-vibes-when-is-a-generative-model-useful/" />
  <id>urn:https-www-williamjbowman-com:-blog-2026-03-05-against-vibes-when-is-a-generative-model-useful</id>
  <published>2026-03-05T23:58:20Z</published>
  <updated>2026-03-05T23:58:20Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;Let&amp;rsquo;s suppose I wanted to answer a question: is the tool X useful for the task Y. If I were scientific about this, I would analyze the properties of tool X and develop a model, and the task Y and the requirements for it and develop a model, and I would use my models to predict the behaviour of tool X in the context of task Y. &amp;ldquo;Can I use timber instead of stainless steel as a support beam for this structure?&amp;rdquo; &amp;ldquo;Will this acid be an appropriate solvent for this reaction?&amp;rdquo; &amp;ldquo;Will this programming language provide these real-time guarantees?&amp;rdquo;&lt;/p&gt;

&lt;p&gt;The discourse on generative models is not like this. Instead, you get claims like &amp;ldquo;software engineering is dead&amp;rdquo;, and attempts to shove generative models into literally everything without a thought. Search? Generative models. Code completion? Generative models. Summarization? Generative models. Voice to text? Generative models. Stock images? Generative models.&lt;/p&gt;

&lt;p&gt;Any attempt to criticize this tends to go in circles and/or have people arguing past each other. Is a generative model useful for internet search? Well, look, it produces text that is plausibly related to the input prompt, so. So&amp;hellip; what? That doesn&amp;rsquo;t answer the question. But the newest models are so much better! Better at.. what?&lt;/p&gt;

&lt;p&gt;I was upset about this when it was being called &amp;ldquo;prompt engineering&amp;rdquo;, and found no sign of engineering, but instead a series of vibes about how to phrase a prompt in a particular version of a particular model, which sometimes produced output that is plausibly related to the input prompt and therefore plausibly close to what you might have intended. I&amp;rsquo;m upset now when people are making claims that agents are so useful, but can&amp;rsquo;t tell me when or why or how they&amp;rsquo;re useful beyond vibes about feeling more productive (vibes that have been refuted by real science contrasting objective measure of productivity vs. subjective reports), or examples of having produced a lot of plausible output.&lt;/p&gt;

&lt;p&gt;(Okay, there are some researchers doing actual science and writing papers; I&amp;rsquo;m talking about the arguments being made as this stuff is integrating into schools, workplaces, etc.)&lt;/p&gt;

&lt;p&gt;I want to &lt;em&gt;know&lt;/em&gt; when generative models are &lt;em&gt;useful&lt;/em&gt;. I don&amp;rsquo;t want to &lt;em&gt;feel&lt;/em&gt; like they&amp;rsquo;re useful, that&amp;rsquo;s just a vibe. I&amp;rsquo;ve been a generative model skeptic basically from the beginning. I could not convince myself that generative models were useful. But I was also skeptical of my own subjective experience. I could imagine that a model capable of produce code from natural language would be useful, in some use cases that I had not found. I imagine there must be a model of when a generative model X is useful for task Y.&lt;/p&gt;

&lt;p&gt;In this post, I&amp;rsquo;m not addressing ethical, political, or social questions. Those questions are important, and I want to address them separately from what the technology is capable of. Just for context: I think the widespread deployment of this technology is deeply problematic and irresponsible. I think further investment in it at its current scale is an almost criminal level of fiduciary negligence and will cause economic harm. I think the ethics of all of this are deeply troubling.&lt;/p&gt;

&lt;p&gt;But for now, I just want to know what they&amp;rsquo;re technically capable of.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;h2 id="a-model-of-generative-model-utility"&gt;A model of generative model utility&lt;/h2&gt;

&lt;p&gt;I think the usefulness of a generative model is a function of three things:&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;What is the cost of encoding a generative task in a prompt vs. directly producing the artifact? This is a function of the task, the model, and the user.&lt;/li&gt;
 &lt;li&gt;What is the cost of verifying the generated artifact meets requirements vs. a directly produced artifact? This is mostly a function of the task and the user, but also the generative model.&lt;/li&gt;
 &lt;li&gt;How much is the task dependent on the artifact vs. the process? This is a function of the task.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;Each of these touch on things many others have said, but I think all three considered simultaneously are important. They make it possible to be scientific in an argument about the use of generative models.&lt;/p&gt;

&lt;p&gt;If you want to claim a new model is &amp;ldquo;more useful&amp;rdquo;, you must specify all of these variables. You must specify a class of tasks, and demonstrate the cost of encoding for some set of users is lower than directly producing the artifacts of tasks; or that perhaps encoding is higher, but that verifying design requirements is lower.&lt;/p&gt;

&lt;p&gt;More importantly, if I want to predict whether a generative model will be useful, I have a model to work with.&lt;/p&gt;

&lt;p&gt;My model predicts that usefulness of a generative model may decrease as task complexity increases. Generative models are probabilistic: the output will be less likely to satisfy complex requirements, particularly if those requirements differ from common patterns in the training data, or worse, &lt;em&gt;subtly&lt;/em&gt; different from common patterns. Verifying complex requirements is also hard, and harder than having a human following good engineering processes that lead to more easily verified outputs.&lt;/p&gt;

&lt;p&gt;On the other hand, generative models should be useful when directly creating the artifact is hard for the user, but verifying the artifact is trivial. This could be the case for artifacts that require cross-referencing extremely specific information that is time consuming for a user to do, but once done, is trivial to check. It could also be the case for generative models integrated into formal verification systems with extremely reliable and highly automated verification, where no knowledge of the artifact being generated is necessary. But in general, it is unlikely to be the case for a novice in some domain trying to generate a complex artifact, since the user will not have the expertise to ensure the output meets requirements. This predicts there will still be a need for users of generative models to have domain expertise.&lt;/p&gt;

&lt;p&gt;The model also predict that generative models are essentially useless for tasks that are highly process dependent, since all a generative model can do is produce an artifact by a blackbox process.&lt;/p&gt;

&lt;h3 id="1-relative-encoding-cost"&gt;1. Relative Encoding Cost&lt;/h3&gt;

&lt;p&gt;A lot of arguments in favour of the usefulness of generative models make arguments about, in essence, the relative encoding cost. For a generative model to be useful, the total encoding cost must be lower than the total cost of directly producing the artifact.&lt;/p&gt;

&lt;p&gt;The total encoding cost includes all the work that goes in to writing a prompt, and all of the compute required to run the prompt. If the task is simple to express in a prompt, the total encoding cost is low. If the task is both simple to express in a prompt, and tedious or difficult to produce directly, the relative encoding cost is low. As models get more capable, more complex prompts can be easily expressed: more semantically dense prompts can be used, referencing more information from the training data. An agent capable of refining or retrying a task after an initial prompt might succeed at a complex task after a single simple prompt. However, both of these also increase the compute cost of the prompt, sometimes substantially, driving up the total encoding cost. More &amp;ldquo;capable&amp;rdquo; models may have a higher probability of producing correct output, reducing costs reprompting with more information (&amp;ldquo;prompt engineering&amp;rdquo;), and possibly reducing verification costs.&lt;/p&gt;

&lt;p&gt;Moreover, as a &lt;em&gt;user&lt;/em&gt; gets more capable, they may be able to complete the tasks directly much faster than they can prompt a model to do it, driving up the relative encoding cost.&lt;/p&gt;

&lt;p&gt;One may argue that the newest models are &amp;ldquo;more powerful&amp;rdquo; or &amp;ldquo;actually intelligent&amp;rdquo; or whatever. But these are unscientific claims.&lt;/p&gt;

&lt;p&gt;The scientific version of these claims is &amp;ldquo;the total encoding cost (for some class of tasks) is lower than previous models&amp;rdquo;. Phrased this way, it&amp;rsquo;s clear this still doesn&amp;rsquo;t mean the new models are useful.&lt;/p&gt;

&lt;p&gt;For most of my tasks, I think the relative encoding cost has been high. Many of my software engineering tasks are constructing small, semantically dense programs, with very specific design requirements, in a language much more concise than English that I can write fluently. I can systematically design and implement such software faster than I can encode the specification into a prompt for a generative model.&lt;/p&gt;

&lt;p&gt;As one example, I tried using Claude Opus 4.6 to generate a program that would interpret a custom DSL I use for typesetting grammars, and generate Haskell type definitions. After 8 hours of prompting, several million tokens, the code it generated was still absolutely useless. It passed the tests I had prompted it on, but just looking at the code, one could easily identify type errors and logic that tried to special case specific identifiers from the tests. The logic for sanitizing identifiers was a mess, and would occasionally generate empty strings. A correct implementation would take me 300&amp;mdash;400 line of code to write, which I can certainly write in less than 8 hours.&lt;/p&gt;

&lt;p&gt;However, not true of &lt;em&gt;all&lt;/em&gt; tasks are writing semantically dense code with very tight design requirements. For example, I was recently trying to install a package whose name I forgot. I prompted the model to &amp;ldquo;install that x11 fake gui thing&amp;rdquo;, a trivial prompt. Actually completing the task myself would have required a lot of &lt;em&gt;tedious&lt;/em&gt; work, with lots of accidental complexity. I would have needed to search the internet to identify the name of this software, cross-reference that with the distribution of the operating system I was running and the name used by its package manager, possibly cross-reference the installation command for this particular package manager, and then write and execute a shell script to perform the install. I was able to use the agent to do all of this with an extremely easy to write prompt. This task had a very low relative encoding cost.&lt;/p&gt;

&lt;h3 id="2-relative-verification-cost"&gt;2. Relative Verification Cost&lt;/h3&gt;

&lt;p&gt;Some arguments about generative models focus on verification: &amp;ldquo;formal verification will become more important as more code is generated&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;I think these arguments are also unscientific. Verification is also not magic. Software designed in one way may be easier to verify than in another way. A user who carefully designed and implemented the software may be able to more easily verify it than when dropped into a fully generated code base.&lt;/p&gt;

&lt;p&gt;All of this depends on the task, the user, and what the model is capable of generating. For my prompt to install a package, verification is trivial. I will recognize the right command when I see it, and it&amp;rsquo;s one line long.&lt;/p&gt;

&lt;p&gt;Relative verification cost also goes up with the size of the task. If you&amp;rsquo;re generating a 1 line script, no problem. If you&amp;rsquo;re trying to generate a very large artifact, you&amp;rsquo;re going to get bored validating every command, every edit. You&amp;rsquo;re not going to be able to check every line of code that was generated. You&amp;rsquo;re going to need some other approach to verifying the output, increasing cost.&lt;/p&gt;

&lt;p&gt;Relative verification cost also depends on the user. If I&amp;rsquo;m prompting a model to produce Racket, a language I am very fluent in, I can quickly evaluate the design and implementation of the generated code. If I tried to prompt a model to produce C, I&amp;rsquo;d be far better off just writing the C myself, following a systematic approach that would result in safe C. And then running it in a sandbox. After running some sanitizers on it.&lt;/p&gt;

&lt;p&gt;Relative verification cost somewhat depends on the capabilities of the model, too. Some of the early models I experimented with produced trash code. Not merely bad code with bad design, but errors so basic I wouldn&amp;rsquo;t think to look for them: it would produce Racket with mismatched parenthesis, references to functions that didn&amp;rsquo;t exist, etc. Those are easy enough to detect by running the compiler, but what about the ones that aren&amp;rsquo;t so easy to detect?&lt;/p&gt;

&lt;p&gt;One key part of this relative verification cost is that generative models produce &lt;em&gt;plausible output&lt;/em&gt;. It&amp;rsquo;s not accurate to say a model produces &amp;ldquo;correct&amp;rdquo; or &amp;ldquo;incorrect&amp;rdquo; output, or &amp;ldquo;makes mistakes&amp;rdquo;. It does exactly what it&amp;rsquo;s designed to do: produce output that is statistically related to the input prompt, in some way. That doesn&amp;rsquo;t mean &amp;ldquo;statistically correct&amp;rdquo;, just &amp;ldquo;statistically related&amp;rdquo;. All output is correct, in the sense that all it&amp;rsquo;s suppose to be is a point in the distribution of things related to the prompt. Maybe you produce C code with memory errors most of the time, but &lt;em&gt;most&lt;/em&gt; C code has memory errors. Maybe you mostly produce correct bash scripts for installing packages, because most bash scripts for installing packages on the internet are correct.&lt;/p&gt;

&lt;p&gt;Plausibility of generative models greatly increases the relative verification cost, since the output is essentially optimized to be &lt;em&gt;close&lt;/em&gt; to correct. I&amp;rsquo;d predict that relative verification cost could &lt;em&gt;go up&lt;/em&gt; as the models get more complex. The class of errors we&amp;rsquo;re likely to find in generated code will be very different than the class of errors we&amp;rsquo;re used to looking for in human generated code: generated code will have &lt;em&gt;subtle&lt;/em&gt; errors. As the models get more capable, you might be more likely to trust the output, and less likely to spot these subtle errors. This cost can be reduced by formal methods, but formal methods aren&amp;rsquo;t necessarily cheap. You might be better off with an engineer following a design process.&lt;/p&gt;

&lt;p&gt;For some tasks, verifying the output may be impossible, or at least impossible without redoing exactly the work you were trying to use a generative model for. I think internet search is a good example of this. A generative model generated response to an internet search query that you did not know the answer too is essentially unverifable, unless you go and search for credible sources to verify the summary. At which point, the generative model did entirely wasted work.&lt;/p&gt;

&lt;h3 id="3-artifact-vs-process"&gt;3. Artifact vs. Process&lt;/h3&gt;

&lt;p&gt;Some tasks aren&amp;rsquo;t about the output. Or maybe they aren&amp;rsquo;t &lt;em&gt;just&lt;/em&gt; about the output, and require the output be created following a specific process.&lt;/p&gt;

&lt;p&gt;Easy examples of this are in education. I don&amp;rsquo;t need students to implement factorial for the one billionth time because I need an implementation of factorial. They implement factorial because going through the process creates knowledge in their head. Writing code is a fundamentally different process than reading code, in the same way that writing this blog post is a fundamentally different process than reading it.&lt;/p&gt;

&lt;p&gt;This blog post is an example of a process-driven task. I&amp;rsquo;m writing this post. My hands are typing the words that appear in this post. They are not merely typing prompts that cause a generative model to generate plausibly-related words. That&amp;rsquo;s because I&amp;rsquo;m not trying to create a blog post. I&amp;rsquo;m trying to create knowledge, within myself and then within others. Writing this post is me thinking through all the details.&lt;/p&gt;

&lt;p&gt;Process-driven tasks also come up in engineering. Some engineering requires specific processes are followed, because if the processes are followed, the end result will satisfy certain properties that may be difficult or impossible to verify just looking at the artifact. A large fruit company, for example, might forbid engineers from contributing to open source projects as part of the process by which they engineer software in order to mitigate intellectual property risks. There is no way, just looking at the software the engineer writes, to guarantee freedom from those risks.&lt;/p&gt;

&lt;p&gt;The process argument against generative models comes up a lot. The argument goes something like &amp;ldquo;X is about human communication, or creativity, so generative models cannot be used to create Y&amp;rdquo;. And I &lt;em&gt;really&lt;/em&gt; sympathize with this argument, because I think far too much is produced by ignoring the process.&lt;/p&gt;

&lt;p&gt;But there are certainly tasks for which I really only* care about the output. My shell script example is one: I don&amp;rsquo;t care how the package gets installed; I care that it&amp;rsquo;s installed. (* Well, assuming the output wasn&amp;rsquo;t produced through some truly problematic process, which, well&amp;hellip; but that&amp;rsquo;s a future post.)&lt;/p&gt;

&lt;p&gt;The same can be true of writing. I am writing this post manually, because the process matters, but some writing is functional. For example, I used a generative model to draft a policy document. Policy documents don&amp;rsquo;t have much creative structure to them; they express a set of rules. I&amp;rsquo;m still reading and redrafting the document, since I need the particulars to better suit me, but it was useful to start from a generated draft, in the same way I might start from a template.&lt;/p&gt;

&lt;p&gt;But even when the output is boring and easily verified, the process may be important. Junior engineers might write lots of boring, easily verified code. It might be extremely cheap the replace them with agents. But junior engineers writing that code are going through a process by which they gain experience, knowledge, and skills. Generative models can replace their output, but nothing can replace that process.&lt;/p&gt;

&lt;p&gt;For almost all software I write, I do care about the process. I&amp;rsquo;m typically designing software as part of research, and me doing the design and implementation work creates knowledge that I will then share. The &lt;em&gt;software&lt;/em&gt; isn&amp;rsquo;t the important output, or not the only important output. I think this is another big reason I haven&amp;rsquo;t found these things useful, and why it&amp;rsquo;s been such a struggle to figure out how they could possibly be useful.&lt;/p&gt;

&lt;h2 id="we-just-need-people-who-can-make-a-computer-produce-useful-work"&gt;We just need people who can make a computer produce useful work&lt;/h2&gt;

&lt;p&gt;So when is a generative model useful? Just when the (1) relative cost of encoding the work in a prompt is low (compared to doing the work some other way); (2) and/or relative cost of verifying the output satisfies requirements is low; (3) and the process used to complete the work doesn&amp;rsquo;t matter. To judge all of this accurately, the user of the model needs to know quite a lot about the work being done, about verifying design requirements in the domain, and about working with generative models and/or the model in question.&lt;/p&gt;

&lt;p&gt;Navigating these trade-offs is engineering. If you&amp;rsquo;re navigating those trade-offs to produce software, you&amp;rsquo;re doing software engineering. If you&amp;rsquo;re not considering these trade-offs, you&amp;rsquo;re just going on vibes and what you produce will be something between accidentally useful and extremely harmful.&lt;/p&gt;

&lt;p&gt;These trade-offs aren&amp;rsquo;t unique to generative models, but one thing is: they&amp;rsquo;ve made it incredibly cheap to produce an immense amount of output that is plausibly described by a natural language description. But plausible doesn&amp;rsquo;t mean useful, and there&amp;rsquo;s nothing in generative models that could ever guarantee useful output. As the models get more sophisticated, the complexity of the output and the prompts are getting more sophisticated. That&amp;rsquo;s not necessarily more useful. As that complexity goes up, so do the costs: of compute, of verification, and of relying on output over process.&lt;/p&gt;

&lt;p&gt;I understand the temptation of these tools. Sometimes useful work is incredibly complex and frustrating to do. Writing software, running scripts, and organizing all my notes can be very tedious. Sometimes that is accidental complexity, but much of the time it is essential. It is very easy to use a generative model produce output. I don&amp;rsquo;t think it&amp;rsquo;s very easy to use them produce useful output.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">What's higher-order about so-called higher-order references?</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2025/06/02/what-s-higher-order-about-so-called-higher-order-references/" />
  <id>urn:https-www-williamjbowman-com:-blog-2025-06-02-what-s-higher-order-about-so-called-higher-order-references</id>
  <published>2025-06-02T21:56:43Z</published>
  <updated>2025-06-02T21:56:43Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;A reviewer, in one of those off-hand little low-level comments they leave, which one is sometimes tempted to ignore as one works on a revision because they&amp;rsquo;re not &lt;em&gt;strictly&lt;/em&gt; actionable, has absolutely nerd-sniped me.&lt;/p&gt;

&lt;p&gt;What does &amp;ldquo;higher-order&amp;rdquo; in &amp;ldquo;higher-order references&amp;rdquo; mean? (References as in &lt;a href="https://doi.org/10.1145/362349.362364"&gt;Reynolds 1970&lt;/a&gt;.)&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;We appear to have inherited the phrase &amp;ldquo;higher-order&amp;rdquo; from higher-order logic, which it refers to the union of first-order logic, and second-order logic, and third-order logic, and so on. Here, &amp;ldquo;order&amp;rdquo; refers to what quantifiers can quantify over. For example, zeroth-order logic has no quantifiers. First-order logic can quantify individuals. Second-order logic can quantify over things that quantify over individuals (sets). &lt;em&gt;Etc.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So what is a higher-order function? Well, a function that can quantify over functions that can quantify over functions, &lt;em&gt;etc&lt;/em&gt;. Really, we could perhaps generalize to higher-order values to make a closer analogy to higher-order logic. A zeroth-order value cannot quantify over other values&amp;mdash;values such as naturals and booleans. These are sometimes called ground values. A function cannot be a zeroth-order value, since it quantifies over other values. A first-order value can quantify over zeroth-order values. A fairly restricted function would be a first-order value. A second-order value could quantify over values that quantify over values, so for example a function of type &lt;code&gt;(A -&amp;gt; B) -&amp;gt; C&lt;/code&gt;, where &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;B&lt;/code&gt;, and &lt;code&gt;C&lt;/code&gt; are ground values, would be second order.&lt;/p&gt;

&lt;p&gt;So far all this makes sense.&lt;/p&gt;

&lt;p&gt;What is a higher-order reference?&lt;/p&gt;

&lt;p&gt;Well&amp;hellip; that is a surprisingly complicated question.&lt;/p&gt;

&lt;p&gt;Of late, &amp;ldquo;higher-order reference&amp;rdquo; seems to mean &amp;ldquo;reference to a higher-order, effectful function&amp;rdquo;. The phrase appears in this sense at least as early as 1998 (&lt;a href="https://doi.org/10.1109/LICS.1998.705669"&gt;Abramsky &lt;em&gt;et al.&lt;/em&gt;&lt;/a&gt;), in which Abramsky &lt;em&gt;et al&lt;/em&gt;. use &amp;ldquo;higher-order reference&amp;rdquo; to refer to references that contain higher-order functions that can, when called, modify the heap. But this use of &amp;ldquo;higher-order&amp;rdquo; is at odds with most other uses of &amp;ldquo;higher-order&amp;rdquo;. It&amp;rsquo;s not used to mean that the reference merely quantifies over other references. Instead, it&amp;rsquo;s used to mean references that quantify over &lt;em&gt;higher-order, effectful functions&lt;/em&gt;, a different class of values. That is, this use of &amp;ldquo;higher-order&amp;rdquo; refers not to the order of the reference, but the order of the values the reference contains. If we were to use &amp;ldquo;higher-order reference&amp;rdquo; more consistently with &amp;ldquo;higher-order logic&amp;rdquo;, it should mean references to references to references &lt;em&gt;etc.&lt;/em&gt; to values.&lt;/p&gt;

&lt;p&gt;The phrase &amp;ldquo;general references&amp;rdquo; avoids the problem, but does not solve it. This phrase is often used, including by &lt;em&gt;op. cit.&lt;/em&gt;, to include other forms of higher quantification in references, such as cyclic references and references to existential types, &lt;em&gt;etc.&lt;/em&gt;, as well as references to higher-order, effectful functions. To quote:&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;By general references we mean references which can store not only values of ground types (integers, booleans, etc.) but also those of higher types (procedures, higher-order functions, or references themselves).&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://www.cs.princeton.edu/techreports/2004/713.pdf"&gt;Ahmed (2004)&lt;/a&gt; uses similar phrasing:&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;general references — that is, mutable cells that can hold values of any closed type including other references, functions, recursive types, and impredicative quantified types.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;The emphasis is on their &lt;em&gt;generality&lt;/em&gt;, which distracts from a key semantic issues (higher-order, effectful functions &lt;em&gt;in particular&lt;/em&gt; are responsible for interesting semantics questions).&lt;/p&gt;

&lt;p&gt;The situation is worse if we look at the phrase &amp;ldquo;first-order references&amp;rdquo;, which also appears in &lt;a href="https://doi.org/10.1109/LICS.1998.705669"&gt;Abramsky &lt;em&gt;et al.&lt;/em&gt;&lt;/a&gt;. This appears to refer to references to ground values, &lt;em&gt;i.e.&lt;/em&gt;, references to zeroth-order values. So a first-order reference is indeed a first-order value, in that it quantifies over zeroth-order values. But that means &amp;ldquo;first-order&amp;rdquo; in &amp;ldquo;first-order reference&amp;rdquo; is used in a difference sense than &amp;ldquo;higher-order&amp;rdquo; in &amp;ldquo;higher-order references&amp;rdquo;: it refers to the order of quantification of the reference itself, and not to the order of the quantification of the contents of the reference.&lt;/p&gt;

&lt;p&gt;Even more frustratingly, it seems the phrase &amp;ldquo;higher-order reference&amp;rdquo; &lt;em&gt;used&lt;/em&gt; to use &amp;ldquo;higher-order&amp;rdquo; in the original sense. &lt;a href="https://doi.org/10.1007/3-540-08342-1_22"&gt;Janssen &lt;em&gt;et al.&lt;/em&gt; (1977)&lt;/a&gt; use &amp;ldquo;higher order reference&amp;rdquo; to refer to references that quantify over references! Readings over some of the related papers around that time, it seems the semantics of such references were quite interesting. It&amp;rsquo;s unclear to me when exactly the phrase took on the new sense of &amp;ldquo;higher-order&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;So how do I concisely, and pedantically, refer to those references that can contain higher-order (effectful) functions (but not necessarily other non-first-order values)? My student Sean Bocirnea proposed &amp;ldquo;higher-order value references&amp;rdquo; (HOVR; pronounced &amp;ldquo;hoover&amp;rdquo;). Perhaps we&amp;rsquo;d use &amp;ldquo;higher-order function reference&amp;rdquo; (HOFR; &amp;ldquo;hoofer&amp;rdquo;) to speak of those only required to contain higher-order functions. These are less verbose than any alterantive I&amp;rsquo;ve come up with, but have bad mouth-feel.&lt;/p&gt;

&lt;p&gt;Given the phrase has had a new sense for at least almost 30-years old at this point, I&amp;rsquo;m a a little reluctant to be inventing new phrases. Perhaps I should just leave it at this, with this note serving as a historical marker of this accident of language. But I&amp;rsquo;m also insufferably pedantic, and the phrase &lt;em&gt;does&lt;/em&gt; have two meanings, so perhaps I should create a new phrase.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">What is a model?</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2023/06/15/what-is-a-model/" />
  <id>urn:https-www-williamjbowman-com:-blog-2023-06-15-what-is-a-model</id>
  <published>2023-06-15T20:25:25Z</published>
  <updated>2023-06-15T20:25:25Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;What is a model, particularly of a programming language? I&amp;rsquo;ve been struggling with this question a bit for some time. The word &amp;ldquo;model&amp;rdquo; is used a lot in my research area, and although I have successfully (by some metrics) read papers whose topic is models, used other peoples&amp;rsquo; research on models, built models, and trained others to do all of this, I don&amp;rsquo;t really understand what a model is.&lt;/p&gt;

&lt;p&gt;Before I get into a philosophical digression on what it even means to understand something, let&amp;rsquo;s ignore all that and try to discover what a model is from first principles.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;h2 id="definitions-of-model"&gt;Definitions of &amp;ldquo;model&amp;rdquo;&lt;/h2&gt;

&lt;p&gt;The apparent place to start to understand the meaning of a word is to read its definition. This is actually no help at all. There are lots of uses of the word &amp;ldquo;model&amp;rdquo;, with several definitions. Here are some.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definition 0&lt;/strong&gt; In science and engineering, a model is &amp;ldquo;an abstract description of a concrete system using mathematical concepts and language&amp;rdquo;. See &lt;a href="https://en.wikipedia.org/wiki/Mathematical_model" title="Mathematical model"&gt;Wikipedia&lt;/a&gt; provides a nice introduction to this kind of model, and the &lt;a href="https://plato.stanford.edu/entries/model-theory/#Modelling" title="Models and Modelling"&gt;Standard Encylopedia of Philosophy&lt;/a&gt; provides a nice explanation in the context of model theory, which will be relevant later in this post.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definition 1&lt;/strong&gt; A &lt;em&gt;syntactic model&lt;/em&gt; (of a type theory) is defined by &lt;a href="https://doi.org/10.1145/3018610.3018620" title="The Next 700 Syntactical Models of Type Theory"&gt;Boulier, Pédrot, and Tabareau&lt;/a&gt; as a translation from one type theory into another that preserves typing, the definition of false, and definitional equivalence. This syntactic model enables the source type theory to inherit properties of the target type theory&amp;mdash;such as consistency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definition 2&lt;/strong&gt; A &lt;em&gt;model&lt;/em&gt; (of a &lt;em&gt;vocabulary&lt;/em&gt; also called a &lt;em&gt;language&lt;/em&gt; \(\sigma\)) in the sense of model theory (as defined by &lt;a href="https://doi.org/10.1007/978-3-662-07003-1" title="Elements of Finite Model Theory"&gt;Elements of Finite Model Theory&lt;/a&gt;) is a &lt;em&gt;\(\sigma\)-structure&lt;/em&gt; (&amp;ldquo;also called a &lt;em&gt;model&lt;/em&gt;&amp;rdquo;) defining a set &lt;em&gt;A&lt;/em&gt; along with 3 sets providing interpretations of that vocabulary. These sets are \(Ic_A\), which interprets each constant in \(\sigma\) as an element of \(A\), \(IP_A\), which interprets each n-ary predicate symbol or relation symbol from \(\sigma\) as an n-ary (set-theoretic) relation between elements of \(A\), and \(If_A\), which interprets each n-ary function symbol in \(\sigma\) as a (set-theoretic) function from n elements of \(A\) to an element of \(A\).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definition 3&lt;/strong&gt; The above definition is confusing, since it conflates &lt;em&gt;structure&lt;/em&gt; and &lt;em&gt;model&lt;/em&gt;, which the text later distinguishes with the following separate definition. A &lt;em&gt;model&lt;/em&gt; (of a &lt;em&gt;theory&lt;/em&gt; (over a vocabulary \(\sigma\))) is a &lt;em&gt;structure&lt;/em&gt; (&amp;ldquo;also called a &lt;em&gt;model&lt;/em&gt;&amp;rdquo;) of &lt;em&gt;vocabulary&lt;/em&gt; \(\sigma\) such that every sentence in the theory is interpreted in the structure to make the sentence true. (A &lt;em&gt;theory&lt;/em&gt; is a set of sentences drawn from a vocabulary.) My rephrasing of the definition of model is intentionally confusing and difficult to parse, to make apparent the inherit confusingness created by the several layers of definitions and one definition that defines &amp;ldquo;model&amp;rdquo; using a second definition of &amp;ldquo;model&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definition 4&lt;/strong&gt; &lt;a href="https://ncatlab.org/nlab/show/structure+in+model+theory#Definition" title="Definition of 'structure' in model theory"&gt;Nlab hosts an article&lt;/a&gt; with a much clarified definition, which distinguishes &lt;em&gt;language&lt;/em&gt;, &lt;em&gt;theory&lt;/em&gt;, &lt;em&gt;structure&lt;/em&gt;, and &lt;em&gt;model&lt;/em&gt; carefully. In particular, it is careful to only call &lt;em&gt;structure&lt;/em&gt; the interpretation of the &lt;em&gt;language&lt;/em&gt; (call &lt;em&gt;vocabulary&lt;/em&gt; above), and only call &lt;em&gt;model&lt;/em&gt; an interpretation that makes true the &lt;em&gt;axioms&lt;/em&gt; composing the &lt;em&gt;theory&lt;/em&gt; of the &lt;em&gt;language&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definition 5&lt;/strong&gt; &lt;a href="https://twitter.com/carloangiuli/status/1640421574733078528?s=20"&gt;Carlo Anguli once gave me the following definition of model&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;A collection of interpretation functions that interpret every syntactic category in such that the original relationship is respected.&lt;/p&gt;
 &lt;p&gt;e.g., 
  &lt;br /&gt; - interpret every context as a set, 
  &lt;br /&gt; - interpret every (non-dependent) type as a set, and 
  &lt;br /&gt; - interpret every term-of-a-type indexed-by-a-context as an element-of-the-interpretation-of-that-type indexed-by-elements-of-the-interpretation-of-that-context.&lt;/p&gt;
 &lt;p&gt;Implicit in this definition is that the interpretations must respect equality &amp;mdash; because if you don&amp;rsquo;t respect equality of arguments then you&amp;rsquo;re not a function!&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;This definition seems to be close to &lt;strong&gt;Definition 2&lt;/strong&gt;, as it doesn&amp;rsquo;t mention axioms and their interpretation. However, it might be &lt;strong&gt;Definition 3&lt;/strong&gt; instead, as there could be implicit in the definition of &lt;a href="https://www.williamjbowman.com/blog/2023/06/07/what-is-syntax/" title="What is syntax?"&gt;syntax&lt;/a&gt; an inclusion of all judgements of the programming language, and therefore in the phrase &amp;ldquo;such that the original relationship is respected&amp;rdquo; a requirement that axioms of those judgements become true.&lt;/p&gt;

&lt;p&gt;Also implicit in this definition of model is what it is a model &lt;em&gt;of&lt;/em&gt;. Perhaps a programming language, but it again depends on what &lt;a href="https://www.williamjbowman.com/blog/2023/06/07/what-is-syntax/" title="What is syntax?"&gt;syntax&lt;/a&gt; means and thus what &amp;ldquo;every syntactic category&amp;rdquo; refers to.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m interested in the requirement that the interpretation is a collection of &lt;em&gt;functions&lt;/em&gt;, which seems to be missing or only implied in some model theory definitions of &amp;ldquo;model&amp;rdquo;.&lt;/p&gt;

&lt;h2 id="so-what-is-a-model"&gt;So what &lt;em&gt;is&lt;/em&gt; a model?&lt;/h2&gt;

&lt;p&gt;One of the first thing that jumps out to me after reviewing the above definitions is that to understand each definition, you &lt;em&gt;have&lt;/em&gt; to reframe the definition of &lt;em&gt;model&lt;/em&gt; into &lt;em&gt;model [of what]&lt;/em&gt;. It really never makes sense to give a definition of merely &amp;ldquo;model&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definition 0&lt;/strong&gt; defines a &lt;em&gt;model of a system [of the real world]&lt;/em&gt;. &lt;strong&gt;Definition 1&lt;/strong&gt; defines a &lt;em&gt;model of a type theory&lt;/em&gt;. &lt;strong&gt;Definitions 2&lt;/strong&gt; and &lt;strong&gt;3&lt;/strong&gt; give definitions of a &lt;em&gt;model&lt;/em&gt;, in the sense of model theory, but of two different objects: &lt;em&gt;model of a vocabulary (or language)&lt;/em&gt;, which is more often called a structure, and &lt;em&gt;model of a theory&lt;/em&gt; (which everyone seems to agree is a &amp;ldquo;model&amp;rdquo;). &lt;strong&gt;Definition 4&lt;/strong&gt; makes this distinction very clear. &lt;strong&gt;Definition 5&lt;/strong&gt; seems to use &amp;ldquo;model&amp;rdquo; in the model-theoretic sense, but has abstracted a bit away from a particular notion of &lt;em&gt;theory&lt;/em&gt; and generalized to &lt;a href="https://www.williamjbowman.com/blog/2023/06/07/what-is-syntax/" title="What is syntax?"&gt;&lt;em&gt;syntax&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="what-is-a-model-of-a-programming-language"&gt;What is a model &lt;em&gt;of&lt;/em&gt; a programming language?&lt;/h2&gt;

&lt;p&gt;I&amp;rsquo;ve had two problems understanding the word &amp;ldquo;model&amp;rdquo; in the context of programming languages.&lt;/p&gt;

&lt;p&gt;First, we use &amp;ldquo;model&amp;rdquo; in three different senses, and I have neither understood that nor understood the relationships between them.&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;Model in the sense of an abstract description of a system. This is &lt;strong&gt;Definition 0&lt;/strong&gt;. This sense of &amp;ldquo;model&amp;rdquo; means something like &amp;ldquo;mathematical description&amp;rdquo;. What we want is a description in which we can work using math, so we can make predictions about the real world. Ideally, the predictions we make will be true.&lt;/li&gt;
 &lt;li&gt;Model in the strict sense of model theory. These are &lt;strong&gt;Definitions 2, 3, and 4&lt;/strong&gt;. This sense of &amp;ldquo;model&amp;rdquo; is the closet to having a strict definition. It often carries a set-theoretic connotation, asking for a set defining the domain of values, and three interpretation functions that interpret specifics parts of a theory in specific ways.&lt;/li&gt;
 &lt;li&gt;Model in the generalized sense, inheriting from or related to model theory. I hesitate to even call this distinct from the second sense, but I will anyway. I also hesitate to speculate about history&amp;mdash;perhaps this sense actually predates model theory. But I distinguish it from the second sense, because it frequently generalizes away from the strict 3 category &amp;ldquo;constant symbol&amp;rdquo;, &amp;ldquo;predicate symbol&amp;rdquo;, &amp;ldquo;function symbol&amp;rdquo; specification and doesn&amp;rsquo;t seem beholden to set theory. &lt;strong&gt;Definitions 1 and 5&lt;/strong&gt; use &amp;ldquo;model&amp;rdquo; in this sense.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;In the second sense of &amp;ldquo;model&amp;rdquo;, the first sense of the word remains&amp;mdash;we&amp;rsquo;re still interested in a description of some system (the &lt;em&gt;theory&lt;/em&gt;), and of using the model to make predictions or reason. However, since the theory is also mathematical, we can be more rigid about our reasoning requirements&amp;mdash;axioms of the theory &lt;em&gt;must&lt;/em&gt; be true of the model, and relationships &lt;em&gt;must&lt;/em&gt; be preserved in the model. This is rarely true of a model of the real world; &lt;em&gt;e.g.&lt;/em&gt;, the Newtonian model of gravity works pretty well, until it doesn&amp;rsquo;t, so it&amp;rsquo;s a model that doesn&amp;rsquo;t &lt;em&gt;quite&lt;/em&gt; make all axioms true or preserve all relationships.&lt;/p&gt;

&lt;p&gt;The third sense seems closer to the idea of &lt;a href="https://en.wikipedia.org/wiki/Semantics_of_logic" title="Semantics of Logic"&gt;&lt;em&gt;semantics&lt;/em&gt;&lt;/a&gt;, in the mathematical logic sense of the word as assigning meaning or interpretation to &lt;a href="https://www.williamjbowman.com/blog/2023/06/07/what-is-syntax/" title="What is syntax?"&gt;syntax&lt;/a&gt;. In this sense, the word &amp;ldquo;model&amp;rdquo; frequently avoid committing to set theory as a formal foundation, generalizes away from the three interpretation functions, and focuses instead on the &lt;em&gt;relationships&lt;/em&gt; between uninterpreted &lt;a href="https://www.williamjbowman.com/blog/2023/06/07/what-is-syntax/" title="What is syntax?"&gt;syntax&lt;/a&gt; being preserved by the interpretation. For example, in &lt;strong&gt;Definition 1&lt;/strong&gt;, the relationships of interest are well-typedness, definitional equivalence, and falsehood, and the formal foundation is type theory. Category theory seems to come closest to a complete formalization of this sense of the word &amp;ldquo;model&amp;rdquo;, although I&amp;rsquo;ve had a hell of a time understanding that. Nlab articles don&amp;rsquo;t say this explicitly, but reading between the lines in articles linked to from &lt;a href="https://ncatlab.org/nlab/show/model+theory" title="Nlab Article on Model Theory"&gt;the Nlab article on model theory&lt;/a&gt; for the words &lt;a href="https://ncatlab.org/nlab/show/internal+language" title="Nlab Article linked from 'syntax'"&gt;syntax&lt;/a&gt; and &lt;a href="https://ncatlab.org/nlab/show/structure" title="Nlab Article linked from 'semantics'"&gt;semantics&lt;/a&gt; implies that the &lt;a href="https://www.williamjbowman.com/blog/2023/06/07/what-is-syntax/" title="What is syntax?"&gt;idea of syntax&lt;/a&gt;, &lt;em&gt;i.e.&lt;/em&gt;, uninterpreted symbols with relationships between themselves and judgements about them, can be formalized in category theory, and then so can the idea of semantics, &lt;em&gt;i.e.&lt;/em&gt;, providing an interpretation in some other domain of those uninterpreted symbols; a domain in which one can use all the power of the other domain to reason about the judgements one wishes to make about the uninterpreted symbols.&lt;/p&gt;

&lt;p&gt;The second problem with the word &amp;ldquo;model&amp;rdquo; is that we frequently work with two senses simultaneously.&lt;/p&gt;

&lt;p&gt;When I write down a programming language, I&amp;rsquo;m often trying to &lt;em&gt;model&lt;/em&gt; (in the first sense) a real programming language (or some feature of it), one actual software developers use to make real things happen in the real world. I am not merely describing a mathematical object for study. (Okay, sometimes I do that, but usually to the first end, eventually.) When I write down such a model, I may describe the abstract syntax, the typing judgement, and an abstract machines or reduction rules. These form a pretty good mathematical description of how a real language behaves. A compiler will reject syntactically invalid expressions. It may then type check the abstract syntax tree, and reject some possibly semantically invalid expressions. If judged well typed, the compiler may transform the tree into something that runs, and that run-time behaviour can be predicted using the reduction rules.&lt;/p&gt;

&lt;p&gt;However, for much programming languages work, I&amp;rsquo;m not interested in merely predicting the behaviour of a single program. I might want to predict behaviour or properties of the entire language, or its typing judgement, etc. To reason about single programs, the &lt;em&gt;model&lt;/em&gt; (in the first sense) may work well. But it might not work well for, say, trying to decide whether certain types can even be inhabited. To solve this, we might build a &lt;em&gt;model&lt;/em&gt; (in the second or third sense). We interpret the abstract syntax tree and typing judgement in some other domain. That is, the AST and the typing judgement, being a &lt;em&gt;model&lt;/em&gt; in the first sense, form a &lt;em&gt;theory&lt;/em&gt; in the model theoretic sense. We can then construct a model (in the second sense) of a model (in the first sense). The Standard Encyclopedia of Philosophy &lt;a href="https://plato.stanford.edu/entries/model-theory/#Modelling" title="Models and Modelling"&gt;article on model theory&lt;/a&gt; goes into this in detail in the context of model theory, which is great.&lt;/p&gt;

&lt;p&gt;What&amp;rsquo;s more interesting is how these two senses of model interact in programming languages. If one is interested in a model, in the second sense, it may inform how one develops a model (in the first sense). If I know I will want to construct a model (in the second sense) to reason about the typing judgement, I may decide that single-step reduction rules are actually irrelevant; I only care that certain program equivalences hold, really, and any implementation that has those equivalences suffices. So rather than create a model (in the first sense) with an abstract machine or small-step operational semantics, I&amp;rsquo;ll specify an equivalence judgement. This might give less predictive power about a real world implementation, but allow the predictions I do make to apply to many implementations.&lt;/p&gt;

&lt;p&gt;If you see these patterns, you may have some insight into how the author is approaching their work, and in what senses they are using the word &amp;ldquo;model&amp;rdquo;.&lt;/p&gt;
&lt;!-- ## References--&gt;</content></entry>
 <entry>
  <title type="text">What is syntax?</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2023/06/07/what-is-syntax/" />
  <id>urn:https-www-williamjbowman-com:-blog-2023-06-07-what-is-syntax</id>
  <published>2023-06-07T20:58:46Z</published>
  <updated>2023-06-07T20:58:46Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;I&amp;rsquo;m in the middle of confronting my lack of knowledge about denotational semantics. One of the things that has confused me for so long about denotational semantics, which I didn&amp;rsquo;t even realize was confusing me, was the use of the word &amp;ldquo;syntax&amp;rdquo; (and, consequently, &amp;ldquo;semantics&amp;rdquo;).&lt;/p&gt;

&lt;p&gt;For context, the contents of this note will be obvious to perhaps half of programming languages (PL) researchers. Perhaps half enter PL through math. That is not how I entered PL. I entered PL through software engineering. I was very interested in building beautiful software and systems; I still am. Until recently, I ran my own cloud infrastructure&amp;mdash;mail, calendars, reminders, contacts, file syncing, remote git syncing. I still run some of it. I run secondary spam filtering over university email for people in my department, because out department&amp;rsquo;s email system is garbage. I am &lt;em&gt;way&lt;/em&gt; better at building systems and writing software than math, but I&amp;rsquo;m interested in PL and logic and math nonetheless. Unfortunately, I lack lot of background and constantly struggle with a huge part, perhaps half, of PL research. The most advanced math course I took was Calculus 1. (well, I took a graduate recursion theory course too, but I think I passed that course because it was a grad course, not because I did well.)&lt;/p&gt;

&lt;p&gt;So when I hear &amp;ldquo;syntax&amp;rdquo;, I think &amp;ldquo;oh sure. I know what that is. It&amp;rsquo;s the grammar of a programming language. The string, or more often the tree structure, used to represent the program text.&amp;rdquo;. And that led me to misunderstand half of programming languages research.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;h2 id="the-first-meaning-of-syntax"&gt;The First Meaning of Syntax&lt;/h2&gt;

&lt;p&gt;Syntax has two meanings in programming languages, and both meanings can frequently be found in the same paper.&lt;/p&gt;

&lt;p&gt;The first meaning is the one I gave above. I could give a definition of the syntax (in the first sense) of the lambda-calculus as follows.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;e ::= x | (lambda (x) e) | (e e)&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ah. Beautiful syntax.&lt;/p&gt;

&lt;p&gt;If we were following a standard text, such as &lt;a href="http://www.cs.cmu.edu/~rwh/pfpl/2nded.pdf"&gt;Harper&amp;rsquo;s &lt;em&gt;Practical Foundation for Programming Languages (2nd ed)&lt;/em&gt;&lt;/a&gt;, we might next define the &amp;ldquo;semantics&amp;rdquo; of this &amp;ldquo;syntax&amp;rdquo;. We might define the &amp;ldquo;static semantics&amp;rdquo;, &lt;em&gt;i.e.&lt;/em&gt;, the type system or binding rules, then the &amp;ldquo;dynamic semantics&amp;rdquo;, &lt;em&gt;i.e.&lt;/em&gt;, the rules governing the evaluation behaviour of the syntax. For example, I might write the following small-step operational semantics.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;((lambda (x) e) e') -&amp;gt; e[x := e']&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ah. Beautiful semantics.&lt;/p&gt;

&lt;p&gt;Except, everything I wrote above, reduction rule included, is also &lt;em&gt;syntax&lt;/em&gt; and &lt;em&gt;not semantics&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id="historical-interlude"&gt;Historical Interlude&lt;/h2&gt;

&lt;p&gt;The words &amp;ldquo;syntax&amp;rdquo; and &amp;ldquo;semantics&amp;rdquo; come from mathematical logic.&lt;/p&gt;

&lt;p&gt;In that context, &amp;ldquo;syntax&amp;rdquo; describes sentences, statements, symbols, formulas, etc, without respect to any meaning. You can write down a logical formula say as "∀ X.P(X, A)" (where &amp;ldquo;A&amp;rdquo; is a logical constant, &amp;ldquo;X&amp;rdquo; is a variable, &amp;ldquo;P&amp;rdquo; is a proposition), and it has no meaning; it&amp;rsquo;s mere syntax. It might be true, or might be false, depending on its interpretation of &amp;ldquo;P&amp;rdquo;, &amp;ldquo;A&amp;rdquo;, and "∀". I could say that it means &amp;ldquo;all leaves are green&amp;rdquo;, which would be false. A more relevant example for PL might be the syntax &lt;code&gt;((lambda (x) x+1) 2) = 3&lt;/code&gt;, which I would certainly like to be true, but it very much depends on what I mean. If &lt;code&gt;+&lt;/code&gt; means string append as in JavaScript, then the statement is false since &lt;code&gt;''.concat(1, 2) = '12'&lt;/code&gt;. Wikipedia is a good start for trying to understand this history of the word &amp;ldquo;syntax&amp;rdquo;: &lt;a href="https://en.wikipedia.org/wiki/Syntax_(logic)"&gt;https://en.wikipedia.org/wiki/Syntax_(logic)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By contrast, in that same context, &amp;ldquo;semantics&amp;rdquo; is the means by which syntax is given an interpretation. Perhaps the most widely used approach to providing an interpretation of syntax is model theory, which I never learned. In model theory, we start with a &amp;ldquo;syntax&amp;rdquo; (or &amp;ldquo;theory&amp;rdquo;). This theory is a collection of constants, function symbols, and predicate symbols. A model then is a map from the uninterpreted syntax to some interpretation that preserves relationships. I&amp;rsquo;ll say more of this in a later post, but for now, consider the following example. I might provide a model of our earlier example that interprets &lt;code&gt;+&lt;/code&gt; as &lt;code&gt;''.concat&lt;/code&gt;, and &lt;code&gt;=&lt;/code&gt; is mapped to, say &lt;code&gt;===&lt;/code&gt;. This preserves relationships, if all my constants are mapped to strings. Wikipedia is a good source for this history too: &lt;a href="https://en.wikipedia.org/wiki/Semantics_of_logic"&gt;https://en.wikipedia.org/wiki/Semantics_of_logic&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="when-semantics-is-the-syntax"&gt;When Semantics is the Syntax&lt;/h2&gt;

&lt;p&gt;What&amp;rsquo;s interesting about this history is how it was adopted in programming languages, and evolved in two different ways. On the one hand, a programming language grammar is &lt;em&gt;syntax&lt;/em&gt;, in the sense of being uninterpreted statements. That syntax can be given a semantics, an interpretation, by using operation semantics (this is the sense in which operational semantics &lt;em&gt;is&lt;/em&gt; a semantics). The operational semantics provides an interpretation to our grammar.&lt;/p&gt;

&lt;p&gt;But, in another sense, the grammar, typing rules, and evaluation rules (the &amp;ldquo;syntax&amp;rdquo;, &amp;ldquo;static semantics&amp;rdquo;, and &amp;ldquo;dynamic semantics&amp;rdquo;) are mere syntax, in the older logical sense. They are a theory, in the model-theoretic sense. To see why, we must understand what the earlier example &lt;code&gt;((lambda (x) x+1) 2) = 3&lt;/code&gt; means. Or in fact, realize that it doesn&amp;rsquo;t mean anything at all.&lt;/p&gt;

&lt;p&gt;To write this down is to write down a proposition about the grammar: that one piece of the grammar is equal to another. Except I didn&amp;rsquo;t write a proposition that the two were equal. I wrote the uninterpreted proposition symbol &lt;code&gt;=&lt;/code&gt;, the syntax &lt;code&gt;=&lt;/code&gt;, next to two pieces of uninterpreted grammar, two other pieces of syntax. Every syntactic judgment about our grammar is itself syntax, in the model theoretic sense. At least, this is true if we follow the tradition of writing them down synthetically, axiomatically, about the grammar, as is done in standard programming languages textbooks such as &lt;a href="https://www.worldcat.org/search?q=bn:0262162091"&gt;&lt;em&gt;Types and Programming Languages&lt;/em&gt;&lt;/a&gt; or &lt;a href="http://www.cs.cmu.edu/~rwh/pfpl/2nded.pdf"&gt;&lt;em&gt;Practical Foundations for Programming Languages&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this view, the typing rules and reduction relations are syntax. This is a bizarre perspective from a software engineering perspective, but makes sense from the mathematical logic perspective.&lt;/p&gt;

&lt;p&gt;With this perspective, it might make sense to call &amp;ldquo;operational semantics&amp;rdquo; &amp;ldquo;syntactic semantics&amp;rdquo;, or to imagine a tower of syntax and semantics where one level&amp;rsquo;s semantics become the next level&amp;rsquo;s syntax. This view finally helped me make sense of why we call &amp;ldquo;syntactic logical relations&amp;rdquo; &lt;em&gt;syntactic&lt;/em&gt;, when they are clearly semantics. (A problem I danced around in &lt;a href="https://www.williamjbowman.com/blog/2023/03/24/what-is-logical-relations/"&gt;my previous post on logical relations&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;This perspective is also useful, for two reasons. The first is that reasoning purely syntactically, while very general, prevents you from importing any other reasoning principles from any other domain. By viewing the typing system as syntax, and then building a model of it (and by necessity, the programming language terms) in, say, set theory, we can import all set-theoretic reasoning in our attempts to reason about our type system. But more than that, we can reinterpret the syntax freely, to prove general results. While I might have written a type system using syntax that looks like numbers, I could build a model that interprets that type system as over strings, and know that actually the entire system is safe for strings, too. Appropriately generalized, I wouldn&amp;rsquo;t need to do any additional proofs.&lt;/p&gt;

&lt;p&gt;Unfortunately, this double meaning of the word syntax seems to be completely taken for granted by some. nLab is a good example of this. To quote from the introduction to the nLab model theory page:&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;On the one hand, there is &lt;a href="https://ncatlab.org/nlab/show/internal+language"&gt;syntax&lt;/a&gt;. On the other hand, there is &lt;a href="https://ncatlab.org/nlab/show/structure"&gt;semantics&lt;/a&gt;. Model theory is (roughly) about the relations between the two: model theory studies classes of &lt;a href="https://ncatlab.org/nlab/show/models"&gt;models&lt;/a&gt; of &lt;a href="https://ncatlab.org/nlab/show/theories"&gt;theories&lt;/a&gt;, hence classes of “&lt;a href="https://ncatlab.org/nlab/show/structures+in+model+theory"&gt;mathematical structures&lt;/a&gt;”.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;What&amp;rsquo;s most interesting about this quote isn&amp;rsquo;t what it says, but what it links to. The link for &amp;ldquo;syntax&amp;rdquo; is to the page on the internal logic of a category. From the software perspective, this is not syntax, but semantics. How on earth could it be syntax? The link for &amp;ldquo;semantics&amp;rdquo; is to the page on structure, the idea of equipping a category with a particular functor. How on earth is that any more semantics than the original abstract nonsense version of syntax?&lt;/p&gt;

&lt;p&gt;Before I understood &amp;ldquo;syntax&amp;rdquo;, I couldn&amp;rsquo;t make any sense of that, but now I&amp;rsquo;m beginning to understand. The internal logic of a category in some sense must be able to express the grammar of a language, and the judgments of a language, but in a purely syntactic way&amp;mdash;in the same way that when I write down the grammar and typing rules of a language, I don&amp;rsquo;t refer to any interpretation of those symbols beyond the way I combine them on the page. Then the semantics or structure is a the particular functor over that category, providing an interpretation, a semantics, of that original category (the syntax).&lt;/p&gt;

&lt;p&gt;Anyway, now I think I&amp;rsquo;m ready to understand what a model is.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">In What Sense is WebAssembly Memory Safe?</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2023/05/18/in-what-sense-is-webassembly-memory-safe/" />
  <id>urn:https-www-williamjbowman-com:-blog-2023-05-18-in-what-sense-is-webassembly-memory-safe</id>
  <published>2023-05-19T02:35:56Z</published>
  <updated>2023-05-19T02:35:56Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;I&amp;rsquo;ve been trying to understand the semantics of memory in WebAssembly, and realized the &amp;ldquo;memory safety&amp;rdquo; doesn&amp;rsquo;t mean what I expect in WebAssembly.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;h2 id="what-is-memory-safety"&gt;What is memory safety?&lt;/h2&gt;

&lt;p&gt;Here are some definitions.&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;Memory safety is a feature of programming languages that prevents certain types of memory-access bugs, such as out-of-bounds reads and writes, and use-after-free bugs. In an app that manages a list of to-do items, for example, an out-of-bounds read could involve accessing the nonexistent sixth item in a list of five, while a use-after-free bug could involve accessing one of the items on an already deleted to-do list.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt; &lt;a href="https://spectrum.ieee.org/memory-safe-programming-languages"&gt;https://spectrum.ieee.org/memory-safe-programming-languages&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;Memory safety is the state of being protected from various software bugs and security vulnerabilities when dealing with memory access, such as buffer overflows and dangling pointers. For example, Java is said to be memory-safe because its runtime error detection checks array bounds and pointer dereferences.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt; &lt;a href="https://en.wikipedia.org/wiki/Memory_safety"&gt;https://en.wikipedia.org/wiki/Memory_safety&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="memory-unsafety-in-wasm"&gt;Memory (un)safety in Wasm&lt;/h2&gt;

&lt;p&gt;WebAssembly (Wasm) is a &lt;em&gt;language&lt;/em&gt; that guarantees &amp;ldquo;type safety &amp;hellip; [preventing] invalid calls or illegal accesses to locals, &amp;hellip; memory safety, and &amp;hellip; inaccessibility of code addresses or the call stack&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;(Technically, the Wasm paper describes Wasm as a binary code format, that happens to be presented as a language.)&lt;/p&gt;

&lt;p&gt;Formally, a whole Wasm program that type checks is guaranteed to either be a well-typed value, or take an evaluation step to a well-typed program, or evaluate to the well-known dynamic error &amp;ldquo;trap&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;This is in contrast to an unsafe language like C. A well-typed C program might take a step to a well-typed program, or it might evaluate to a value of arbitrary type or no type. For example, a well-typed program of type &lt;code&gt;char&lt;/code&gt; that reads from a buffer might evaluate to a well-typed &lt;code&gt;char&lt;/code&gt;, or it might evaluate to an arbitrary integer that does not correspond to any character because you were reading uninitialized memory.&lt;/p&gt;

&lt;p&gt;For example, consider the following C program.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// unsafe.c
#include &amp;lt;unistd.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

int main(int argc, char** argv) {
  char* buf = malloc(0);
  memcpy(buf, "Hello world\n", 12);
  write(1, buf, 12);
  return 0;
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(compiled with &lt;code&gt;clang -o unsafe.exe unsafe.c&lt;/code&gt;; run with &lt;code&gt;./unsafe.exe&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;This program creates a buffer of size &lt;code&gt;0&lt;/code&gt;, writes &amp;ldquo;Hello world\n&amp;rdquo; to it, and tries to print that to standard out. The program printed &amp;ldquo;Hello world&amp;rdquo; when I ran it, but it&amp;rsquo;s undefined behaviour, so anything could happen. I tried to writing a loop that &lt;code&gt;malloc&lt;/code&gt;d lots of memory and wrote arbitrary numbers, but never managed to crash the program. Still, it&amp;rsquo;s not memory safe.&lt;/p&gt;

&lt;p&gt;The equivalent Wasm program is below.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;;; safe.wat
(module
 (import "wasi_unstable" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))

 (memory 0)
 ;;(memory 1)
 (export "memory" (memory 0))

 (data (i32.const 0) "Hello World\n")

 (func $main (export "_start")
       (i32.store (i32.const 12) (i32.const 0))
       (i32.store (i32.const 16) (i32.const 12))
       (call $fd_write (i32.const 1) (i32.const 12) (i32.const 1) (i32.const 20))
       drop))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(run with &lt;code&gt;wasmtime safe.wat&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;In this example, we create a string &amp;ldquo;Hello World\n&amp;rdquo; at address 0 in the module&amp;rsquo;s memory. We then create (encode) a new &lt;code&gt;iovs&lt;/code&gt; just after it, starting as address &lt;code&gt;12&lt;/code&gt;, with a pointer to address &lt;code&gt;0&lt;/code&gt; and length &lt;code&gt;12&lt;/code&gt;. Then we call &lt;code&gt;fd_write&lt;/code&gt;, from the wasi API.&lt;/p&gt;

&lt;p&gt;Unfortunately, we declared the memory size to be &lt;code&gt;0&lt;/code&gt;, so trying to allocate this string fails, traps safely, and the process exits with an error message.&lt;/p&gt;

&lt;p&gt;So wasm is memory safe right?&lt;/p&gt;

&lt;p&gt;Well, sort of, but there&amp;rsquo;s a pretty key distinction here.&lt;/p&gt;

&lt;p&gt;In C, we are creating a new pointer with &lt;code&gt;malloc&lt;/code&gt;. We are allocating a new data structure, then using it (unsafely).&lt;/p&gt;

&lt;p&gt;In Wasm, there is exactly one memory for the entire module. Inside that memory, we encode 2 data structures: our string, and the &lt;code&gt;iovs&lt;/code&gt; structure used by &lt;code&gt;fd_write&lt;/code&gt;. All access to the global memory are safe. But not all accesses to the encoded data structures are.&lt;/p&gt;

&lt;p&gt;Most application will create data structure within the memory. That&amp;rsquo;s what our call to &lt;code&gt;fd_write&lt;/code&gt; did. The two &lt;code&gt;store&lt;/code&gt;s actually create an &lt;code&gt;iovs&lt;/code&gt; structure in the global memory. We have no guarantees, within Wasm, about that data structure.&lt;/p&gt;

&lt;p&gt;For example, here&amp;rsquo;s our Hello World program in Wasm which uses the &lt;code&gt;memory&lt;/code&gt; safely and correctly, but creates an &lt;code&gt;iovs&lt;/code&gt; whose length is claimed to be 100, larger than the actual string.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;;; unsafe.wat
(module
 (import "wasi_unstable" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))

 (memory 1)
 (export "memory" (memory 0))

 (data (i32.const 0) "Hello World\n")

 (func $main (export "_start")
       (i32.store (i32.const 12) (i32.const 0))
       (i32.store (i32.const 16) (i32.const 100))
       (call $fd_write (i32.const 1) (i32.const 12) (i32.const 1) (i32.const 20))
       drop))&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(run with &lt;code&gt;wastime unsafe.wat&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;When I run this, I get &amp;ldquo;Hello world\nd&amp;rdquo; printed to stdout. I have no idea where that trailing &lt;code&gt;d&lt;/code&gt; comes from, and it didn&amp;rsquo;t crash, suggesting it read uninitialized memory of some kind.&lt;/p&gt;

&lt;p&gt;Arguable, this is cheating: Wasm does not and cannot make claims about external system functions, and &lt;code&gt;wasi&lt;/code&gt; is unstable. But IMO the root of the error isn&amp;rsquo;t really about &lt;code&gt;wasi&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Really, the root cause of this error is memory unsafety, but of a data structure encoded within a Wasm module. In a truly memory-safe language, if I try to access the 100th element of a 12-character long string, I get an error:&lt;/p&gt;

&lt;div class="brush: sh"&gt;
 &lt;pre&gt;&lt;code&gt;&amp;gt; racket
Welcome to Racket v8.9 [cs].
&amp;gt; (string-ref "Hello world\n" 100)
; string-ref: index is out of range
;   index: 100
;   valid range: [0, 11]
;   string: "Hello world\n"
; [,bt for context]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But that doesn&amp;rsquo;t happen in Wasm.&lt;/p&gt;

&lt;p&gt;Wasm memory safety doesn&amp;rsquo;t apply to &lt;em&gt;data structures&lt;/em&gt; implemented (encoded) within the &lt;code&gt;memory&lt;/code&gt;. It only applies to the module&amp;rsquo;s &lt;code&gt;memory&lt;/code&gt;, which is protected from other modules, even those running in the same process&amp;rsquo;s virtual address space.&lt;/p&gt;

&lt;p&gt;This means Wasm modules are protected from each other, and so this kind of memory unsafety probably isn&amp;rsquo;t a security risk, only a cause of logic bugs.&lt;/p&gt;

&lt;p&gt;In Wasm, data structures have to be encoded anyway, since Wasm doesn&amp;rsquo;t provide any kind of structure data primitives; you only have integers and some integers are interpreted as addresses into &lt;code&gt;memory&lt;/code&gt;. But, when you encode such data structures in the &lt;code&gt;memory&lt;/code&gt; and use them incorrectly, you have no guarantees about what happens. You could read some arbitrary data (from your own module), or read some uninitialized memory (from your own module). I.e., you get out-of-bounds reads and writes.&lt;/p&gt;

&lt;p&gt;In another view of this, &lt;code&gt;memory&lt;/code&gt; is the only data structure in Wasm, and it is memory safe. That&amp;rsquo;s all the language can be responsible for; if you go about encoding weird things inside that data structure, errors are likely. But this doesn&amp;rsquo;t seem like what people would expect when they hear &amp;ldquo;memory safe&amp;rdquo;. At least, it&amp;rsquo;s not what I expected at first.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">What is logical relations?</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2023/03/24/what-is-logical-relations/" />
  <id>urn:https-www-williamjbowman-com:-blog-2023-03-24-what-is-logical-relations</id>
  <published>2023-03-24T23:32:03Z</published>
  <updated>2023-03-24T23:32:03Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;I have long struggled to understand what a logical relation is. This may come as a surprise, since I have used logical relations a bunch in my research, apparently successfully. I am not afraid to admit that despite that success, I didn&amp;rsquo;t really know what I was doing&amp;mdash;I&amp;rsquo;m just good at pattern recognition and replication. I&amp;rsquo;m basically a machine learning algorithm.&lt;/p&gt;

&lt;p&gt;So I finally decided to dive deep and figure it out: what is a logical relation?&lt;/p&gt;

&lt;p&gt;As with my previous note on realizability, this is a copy of my personal notebook on the subject, which is NOT AUTHORITATIVE, but maybe it will help you.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;Here&amp;rsquo;s my working definition of a logical relation:&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;A realizability semantic model,&lt;/li&gt;
 &lt;li&gt;built of predicates over syntax,&lt;/li&gt;
 &lt;li&gt;that &lt;em&gt;reflects&lt;/em&gt; judgments and structures from semantics to syntax.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;Point 1 is subtle; it implies that the logical relation is both a model, and a &lt;a href="/blog/2022/10/05/what-is-realizability/"&gt;realizability semantics&lt;/a&gt;. Unfortunately, I still don&amp;rsquo;t know what a model is, so I&amp;rsquo;m going to have work with the following probably wrong oversimplification: the logical relation must take (syntactically) equal terms to (semantically) equal terms. Which notion of syntactic equality though? I&amp;rsquo;m not sure, and I&amp;rsquo;m going to ignore it for now.&lt;/p&gt;

&lt;p&gt;Point 2 is actually more specific than necessary. We don&amp;rsquo;t need to predicates over syntax specifically, but really over some base model. It&amp;rsquo;s easier for me to think of this as &amp;ldquo;syntax&amp;rdquo;, though.&lt;/p&gt;

&lt;p&gt;Point 3 is quite difficult to make precise without making a lot of this more precise in a mathematical framework. Jon Sterling gave me the following helpful definition:&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;A logical relation on a model M (viewed as a category) is then a model that is constructed in the following way:&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;
   &lt;p&gt;Choose some functor R : M &amp;mdash;&amp;gt; E where E is a sufficiently structured category (e.g. the category of sets, or something else!). The most basic example of a functor R is the &amp;ldquo;global sections functor&amp;rdquo; M &amp;mdash;&amp;gt; Set, which sends every type in M to the set of &lt;em&gt;closed elements&lt;/em&gt; of that type. This is exactly the usual “non-Kripke logical relations"; to get Kripke logical relations, you replace Set with a functor category (presheaf category) and choose a more interesting functor R.&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;Now define a new category G, as a category whose objects are pairs of an object A of M, together with a subobject of R(A). A morphism in G from (A,A’) to (B, B&amp;rsquo;) is given by a morphism (f : A -&amp;gt; B) that sends elements satisfying A&amp;rsquo; to elements satisfying B&amp;rsquo;.&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;
   &lt;p&gt;You have to show that the category G is actually a model of your language (e.g. show that it has function spaces, booleans, whatever). Doing so is the FTLR.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;
 &lt;p&gt;Note that there are some ways to generalize the situation above, but this is basically what logical relations are.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Point 3 is also is more specific than necessary; &amp;ldquo;syntax&amp;rdquo; can be generalized to be &amp;ldquo;base model&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Despite the complexity, we can see point 3 in action in some examples below.&lt;/p&gt;
&lt;!-- https://types.pl/@wilbowma/110079663033785019--&gt;

&lt;h2 id="what-are-logical-relations-historically"&gt;What are logical relations, historically?&lt;/h2&gt;

&lt;h3 id="tait1967---intensional-interpretations-of-functionals-of-finite-type-i"&gt;tait1967 - Intensional interpretations of functionals of finite type I&lt;/h3&gt;

&lt;p&gt;Logical relations are sometimes called &amp;ldquo;Tait&amp;rsquo;s Method&amp;rdquo;, dating back to &lt;a href="https://doi.org/10.2307/2271658"&gt;Tait&lt;/a&gt;, as far as I can tell.&lt;/p&gt;

&lt;p&gt;In this paper, Tait proves that System T with bar induction is a conservative extension of intuitionistic analysis U_1, which is intuitionistic arithmetic plus quantification over functions plus the axiom (schema) of choice plus bar induction. This conservative extension property is the semantic property of interest. The proof starts with a proof that T without bar induction is a conservative extension of just intuitionistic arithmetic (no choice or bar induction).&lt;/p&gt;

&lt;p&gt;To do this, Tait develops a type-indexed predicate over System T terms (without bar induction), providing a U_0 term for all T terms of each type. These predicates M_t, C_t, and E_t are (I think) what we refer to as a logical relation. In particular, the C_t relation provides the interpretation of T values of type t, M_t seems to deal with variables, and E_t seems to be a binary relation defining semantics (&amp;ldquo;weak α-definitional equality&amp;rdquo;) of terms.&lt;/p&gt;

&lt;p&gt;Theorem V (page 205) uses this logical relation to prove that, for all semantics values at the same type, (weak α-) definitional equality is decidable: they either are or are not related in E_t. This seems to be the key point: the definitional equality is reflected out of the semantics of terms, so it can apply to the syntax of terms.&lt;/p&gt;

&lt;p&gt;This use of logical relation seems to also be a realizability semantics, since it it assigns syntactic types to a collection of semantics terms, by induction over syntactic types, where the realizers are a subset of all possible semantics terms.&lt;/p&gt;

&lt;p&gt;However, it seems to be more than a realizability semantics, too. What seems very important in this paper is that the semantics preserves structure, namely definitional equality. Perhaps implicitly though, other pieces are important. For example, T functions are interpreted as U functions, although it&amp;rsquo;s not clear to me that this is critical.&lt;/p&gt;

&lt;p&gt;This is in contrast to Kleene&amp;rsquo;s (kleene1945) realizability, which did not seem concerned with structure, but only the existence of the realizers.&lt;/p&gt;

&lt;h3 id="plotkin1973---lambda-definability-and-logical-relations"&gt;plotkin1973 - Lambda-definability and logical relations&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.cl.cam.ac.uk/~nk480/plotkin-logical-relations.pdf"&gt;Plotkin&lt;/a&gt; seems to be responsible for the name, and perhaps rediscovering logical relations in the context of programming languages.&lt;/p&gt;

&lt;p&gt;Plotkin helpfully gives us a definition of &amp;ldquo;logical&amp;rdquo;, as well, and it seems quite importantly related to part 3 of my working definition. Plotkin defines a relation R as logical if it is:&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;a subset of any D_k from the carrier any D∞ model (this seems to correspond  to &amp;ldquo;admissible relations&amp;rdquo; in modern logical relations parlance);&lt;/li&gt;
 &lt;li&gt;the relation is preserved by functions in D. That is, the relation holds on a  function f in D_k iff for all arguments x, R(x) implies R (f x)  (extended to the n-ary case for n-ary relations).&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;This suggests that it is important the logical relation is somehow interpreting syntactic structures as semantic structures, as in the case of Tait&amp;rsquo;s model interpreting syntactic functions as semantic functions. More generally, we likely want this property of all structures in the languages: syntactic pairs are interpreted as semantic pairs, etc. Jon&amp;rsquo;s category theoretical definition seems to generalize Plotkin&amp;rsquo;s definition nicely.&lt;/p&gt;

&lt;p&gt;This denotational logical relation also shows us a logical relation that is not defined over syntax. Instead, it is a relation over some arbitrary non-trivial D∞ model. The author mentions that since they can interpret syntax in a D∞ model, they informally treat the logical relation as over syntax sometimes, which I suppose could be made formal easily enough.&lt;/p&gt;

&lt;h2 id="how-is-logical-relations-used-in-pl"&gt;How is &amp;ldquo;logical relations&amp;rdquo; used in PL?&lt;/h2&gt;

&lt;h3 id="ahmed2006---step-indexed-syntactic-logical-relations-for-recursive-and-quantified-types"&gt;ahmed2006 - Step-Indexed Syntactic Logical Relations for Recursive and Quantified Types&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://doi.org/10.1007/11693024_6"&gt;In this paper&lt;/a&gt;, Ahmed is concerned with &lt;em&gt;syntactic&lt;/em&gt; logical relations for recursive and quantified types, in particular for reasoning about contextual equivalence. Likely due to Ahmed&amp;rsquo;s work, this kind of syntactic logical relation seems to be what most people mean or think when they say &amp;ldquo;logical relation&amp;rdquo;, although that may be changing.&lt;/p&gt;

&lt;p&gt;The desired property of the logical relation then is that two related semantic terms should be contextually equivalent in the syntax. That is, the logical relation reflects (from semantics to syntax) equivalence.&lt;/p&gt;

&lt;p&gt;Strangely (for a realizability model), this particular syntactic logical relation also reflects typing: semantic terms in the relation are also guaranteed to be well-typed in the syntax. In contrast, some uses of &amp;ldquo;logical relations&amp;rdquo; enable semantics terms to be syntactically ill-typed. Such logical relations might be better called realizability models, although they do something reflect some structure, so perhaps reflecting typability is not a critical point of reflecting structure.&lt;/p&gt;

&lt;p&gt;Ahmed in the introduction points out an interesting distinction: that logical relations can be either denotational, or syntactic. Syntactic logical relations model syntax as sets of syntactic values such that some property holds over that syntax. By contrast, denotational logical relations model syntax as some denotational object,  Syntactic logical relations are useful for proving properties of the operational semantics directly. Denotational models instead model syntax as denotational objects, such as, &lt;em&gt;e.g.&lt;/em&gt;, sets of set-theoretic functions over elements of a D∞ model in plotkin1973. This is useful for easily proving meta-theoretical properties by reflecting properties of the denotation into the syntax, but not necessarily about the operational semantics directly.&lt;/p&gt;

&lt;p&gt;For example, Tait uses a &amp;ldquo;denotational logical relation&amp;rdquo; into intuitionistic analysis to prove that definitional equality of System T is decidable&amp;mdash;the definition of definitional equality, in the model, and its proof of decidability, are reflected back into the syntax; this requires no operational semantics at all. Plotkin uses a denotational logical relation, into domain theory, to show that certain λ-calculus constructs are or are not definable&amp;mdash;existence of a term in the logical relation is reflected into the syntax as a definable expression. Neither of these is a syntactic logical relation; the semantic values never mention syntactic values directly.&lt;/p&gt;

&lt;p&gt;Ahmed uses a &amp;ldquo;syntactic logical relation&amp;rdquo; to prove something about the operational semantics, namely, to prove contextual equivalence (an operational notion), indirectly. Direct proofs of contextual equivalence are difficult. So instead, a semantic proof of equivalence is reflected back into the syntax as ta proof of contextual equivalence. This requires structuring the logical relation into a denotation of sets of syntactic terms that evaluate in the operational semantics, so that being in the relation tells us something about evaluation in the operational semantics, which tells us something about contextual equivalence.&lt;/p&gt;

&lt;h3 id="abel2018---decidability-of-conversion-for-type-theory-in-type-theory"&gt;abel2018 - Decidability of conversion for type theory in type theory&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://doi.org/10.1145/3158111"&gt;Abel &lt;em&gt;et al.&lt;/em&gt;&lt;/a&gt; define a syntactic logical relation for typed, reducible (and equivalent) terms, to prove decidability of conversion for type theory. Here, the use of syntactic logical relation is important for proving a particular conversion algorithm over the syntax is decidable.&lt;/p&gt;

&lt;p&gt;The interesting feature of this logical relation is the generalization from a model inductively defined over types, to inductively defined over judgments. This demonstrates a weakness in my working definition of logical relation and realizability, since I defined &amp;ldquo;realizability&amp;rdquo; in terms of models inductively defined over types.&lt;/p&gt;

&lt;h3 id="timany2022---a-logical-approach-to-type-soundness"&gt;timany2022 - A Logical Approach to Type Soundness&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://iris-project.org/pdfs/2022-submitted-logical-type-soundness.pdf"&gt;This paper&lt;/a&gt; is interesting because it uses a syntactic logical relation that intentionally does not reflect typing, as many syntactic logical relations cdo. Semantically valid terms are not necessarily syntactically valid. In other ways, it looks very much like a logical relation: syntactic pairs are semantic pairs, sums sums, functions functions, etc.&lt;/p&gt;

&lt;p&gt;The key property this paper is interested in is type safety: all well-typed terms are well-defined in the operational semantics, i.e., they evaluate to values or well-defined errors or fail to terminate, but importantly, do not get stuck. &amp;ldquo;in &lt;em&gt;the&lt;/em&gt; operational semantics&amp;rdquo; is important to understanding why this is a syntactic logical relation; it must model terms as sets of syntactic values to reason about the operational semantics given in the paper.&lt;/p&gt;

&lt;p&gt;However, one could imagine proving a slightly different form of type safety with a denotational logical relation. Giving a logical relation into an arbitrary model with a well-defined notion of evaluation would be implicitly a proof of type safety: that &lt;em&gt;there exists&lt;/em&gt; a model that is type safe. The ability to reflect from semantics to syntax provides a mechanism for constructing that evaluation over syntax. So while the denotational logical relation provides no direct proof about the operational semantics, it may provide a mechanism for a type-safe-by-construction operational semantics. (This reflecting evaluation out of the semantics seems very related to the idea of normalization-by-evaluation, but I&amp;rsquo;m not clear on this.)&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">What is realizability?</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2022/10/05/what-is-realizability/" />
  <id>urn:https-www-williamjbowman-com:-blog-2022-10-05-what-is-realizability</id>
  <published>2022-10-05T21:54:39Z</published>
  <updated>2022-10-05T21:54:39Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;I recently decided to confront the fact that I didn&amp;rsquo;t know what &amp;ldquo;realizability&amp;rdquo; meant. I see it in programming languages papers from time to time, and could see little rhyme or reason to how it was used. Any time I tried to look it up, I got some nonsense about constructive mathematics and Heyting arithmetic, which I also knew nothing about, and gave up.&lt;/p&gt;

&lt;p&gt;This blog post is basically a copy of my personal notebook on the subject, which is NOT AUTHORITATIVE, but maybe it will help you.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;My best understanding of realizability right now, in programming languages (PL) terms, is:&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;A technique for assigning each &lt;em&gt;syntactic type&lt;/em&gt; to a collection of &lt;em&gt;semantic terms&lt;/em&gt;;&lt;/li&gt;
 &lt;li&gt;By &lt;em&gt;induction&lt;/em&gt; over syntactic types;&lt;/li&gt;
 &lt;li&gt;Where the semantic terms that are &lt;em&gt;realizers&lt;/em&gt;&amp;mdash;i.e., included in the collection related to some syntactic type&amp;mdash;are a sub-collection of all possible terms in the semantic domain. That is, there are valid semantic terms not associated with any syntactic type.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;I use the word &amp;ldquo;collection&amp;rdquo; rather than &amp;ldquo;set&amp;rdquo; to avoid invoking set theory.&lt;/p&gt;

&lt;p&gt;Graphically, we can represent this as follows:&lt;/p&gt;

&lt;div class="figure"&gt;&lt;img src="/img/realizability.png" alt="" title="Realizability" /&gt;
 &lt;p class="caption"&gt;&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;The point of the technique is that clause 2 gives us a proof technique by induction, and clause 3 means we can relate the collection of terms (or proofs) to some other well-known collection. This yields a proof technique for metatheoretic properties about the collection, such as that there are only terminating terms in the collection of realizers, or there are only recursive functions and therefore some classical things remain unprovable.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m not entirely sure that clause 2, induction, is necessary, and I can&amp;rsquo;t find anything explicit about clause 3, but they seem to be true historically and in many uses of the term.&lt;/p&gt;

&lt;p&gt;Okay so how did I get to this understanding?&lt;/p&gt;

&lt;h2 id="what-is-realizability-historically"&gt;What is realizability, historically?&lt;/h2&gt;

&lt;h3 id="kleene1945---on-the-interpretation-of-intuitionistic-number-theory"&gt;kleene1945 - On the Interpretation of Intuitionistic Number Theory&lt;/h3&gt;

&lt;p&gt;Realizability seems to come from Kleene&amp;rsquo;s paper &lt;a href="https://doi.org/10.2307/2269016"&gt;&amp;ldquo;On the Interpretation of Intuitionistic Number Theory&amp;rdquo;&lt;/a&gt;. I say &amp;ldquo;seems to&amp;rdquo; as Kleene attributes the &amp;ldquo;detailed investigation of the notion of realizability&amp;rdquo; to David Nelson, attributes several of the results in the paper to Nelson, and claims that the main results of the paper are joint work with Nelson. But the paper only has Kleene&amp;rsquo;s name on it, and Kleene claims in the first footnote that they introduced the idea of realizability to Nelson in a seminar. So anyway, realizability seems to come from Kleene, and this is the canonical paper cited for the technique.&lt;/p&gt;

&lt;p&gt;In this paper, realizability is quite specific. It&amp;rsquo;s a technique that takes an intuitionistic first-order logic formula about Peano arithmetic (Heyting arithmetic) and constructs a natural number from it, representing the (constructive) proof of that formula. Only provable formulas are realized. The point of this exercise is to prove various metatheorems about the realized language: is it consistent, and what are provable/unprovable in the intuitionistic formulae.&lt;/p&gt;

&lt;p&gt;Intuitively, something is unprovable if there exists a formula, but there does not exist a realization of it. This can be shown by connecting the formula to the set of realizers (in this case, natural numbers), but showing that there cannot exist a related natural number (or, more often, function on natural numbers represented by its Gödel number) with the properties required of the realizability interpretation. The simplest example: since &amp;ldquo;false&amp;rdquo; is unprovable (it has no realization, by construction), the intuitionistic logic is consistent.&lt;/p&gt;

&lt;p&gt;This also lets us prove something about the class of all provable statements. Since we have a method for constructing something from any provable (or true) statement, we can say something about the set of all provable statement in relation to the realizers. Kleene mentions one consequence is that the intuitionistic calculus cannot prove the existance of any function other than a general recursive function, since those are the only functions constructed in the realizability interpretation. This tells us, for example, that the intuitionistic calculus is different from classical set theory, which contains other functions.&lt;/p&gt;

&lt;p&gt;An important detail in this paper that clarifies the distinction between the intuitionistic and the classical happens in Clause 6, on page 113. This is the definition of the realizability interpretation for existential quantification ∃x.A(x). This has a realization if, for some &lt;strong&gt;x&lt;/strong&gt;, A(&lt;strong&gt;x&lt;/strong&gt;) has a realization. It&amp;rsquo;s important to notice that this second &amp;ldquo;for some &lt;strong&gt;x&lt;/strong&gt;&amp;rdquo; quantification happens in the metalanguage, namely, classical set theory, and therefore could be choosen by Choice. Kleene discusses this on page 118, where he uses the word &amp;ldquo;classically&amp;rdquo; as a modifier on various quantifiers to remind us that, when working with the quantification and realizers directly, we are working in a classical system in which intuitionistic proofs also exist.&lt;/p&gt;

&lt;p&gt;What seems to be going on here is that the realizers are something like the intuitionistic subset of classical set theory. I think that statement isn&amp;rsquo;t exactly true; Kleene uses classical choice when working with the realizers to show there are unprovable theorems. For example, a realizer parameterized over (classically) &lt;em&gt;all&lt;/em&gt; variables may not correspond to an intuitionistic formula. So it&amp;rsquo;s not that the realizers are only intuitionistic, I think. But any particular realizer is (must be)? The important point may be the realizers are a subset of the whole system, and thus we can prove interesting metatheorems that rely on distinguishing the realizers (and therefore, the formulae they realizer) from all the things in the full system.&lt;/p&gt;

&lt;h3 id="amadio1998---domains-and-lambda-calculi-chapter-15"&gt;amadio1998 - Domains and Lambda-Calculi, Chapter 15&lt;/h3&gt;

&lt;p&gt;Chapter 15 of Amadio and Currien&amp;rsquo;s book &lt;a href="https://doi.org/10.1017/cbo9780511983504"&gt;&amp;ldquo;Domains and Lambda-Calculus&amp;rdquo;&lt;/a&gt; introduces realizability in its historical context. The introduction formalizes Kleene&amp;rsquo;s work as an example, and discusses its use.&lt;/p&gt;

&lt;p&gt;They emphasize two things, which seem to confirm some of my understanding:&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;The realizability relation is defined inductively over &lt;em&gt;formulas&lt;/em&gt;, and relates &lt;em&gt;formulas&lt;/em&gt; to &lt;em&gt;proofs&lt;/em&gt;.&lt;/li&gt;
 &lt;li&gt;The use lets us reason about all &lt;em&gt;proofs&lt;/em&gt; in the system.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;This is the best definition of realizability I&amp;rsquo;ve seen, and applies both to Kleene&amp;rsquo;s original, but also to uses in PL.&lt;/p&gt;

&lt;p&gt;The authors point out that Kleene&amp;rsquo;s original goal was to prove consistency. They then confirm my above intuitions, that the realizability interpretation also lets us prove metatheorems about what is provable/unprovable in the realized system. However, they note that one application of this is to find &lt;em&gt;unprovable&lt;/em&gt; &lt;em&gt;true&lt;/em&gt; statements, which can be consistently axiomatized back into the original system. There are proofs in the set of realizers, i.e., true statements, that are never constructed by the realizability interpretation. These could be added back to the original system to enrich it.&lt;/p&gt;

&lt;p&gt;This latter use seems to confirm one feature of realizability that isn&amp;rsquo;t explicit stated anywhere, but seems to be true of all realizability interpretations I&amp;rsquo;ve seen: that the realizers are a strict subsystem of some larger formal system.&lt;/p&gt;

&lt;h2 id="how-is-realizability-used-in-pl"&gt;How is &amp;ldquo;realizability&amp;rdquo; used in PL?&lt;/h2&gt;

&lt;p&gt;In programming languages, we&amp;rsquo;re not often concerned with intuitionistic vs classical logic; we&amp;rsquo;re working constructively by default. In fact, many of the uses of &amp;ldquo;realizability&amp;rdquo; in PL don&amp;rsquo;t seem to be related to logic at all, but to modeling well-typed programs. And while, sure, these are related by Curry-Howard, the difference seems important to me. So what does realizability mean in this context?&lt;/p&gt;

&lt;p&gt;In most uses in PL, the important feature seems to be clause 3 in my definition above: the collection of all values is larger than the set of realizers. In PL, this suggests that we&amp;rsquo;re ascribing types to &amp;ldquo;untyped&amp;rdquo; terms, and the realizers are those that are semantically well typed, but not necessarily syntactically well typed. The full collection contains also untyped terms, and we can therefore prove through realizability that the type system rules out ill-typed terms.&lt;/p&gt;

&lt;p&gt;There do seem to be some examples in PL that are explicitly relating classical and intuitionistic ideas, namely those trying to import constructive interpretations of classic logic. I&amp;rsquo;m not really interested in those, and I think the connection to realizability is much more clear in those applications, so I&amp;rsquo;ll ignore that area.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;s look at some examples.&lt;/p&gt;

&lt;h2 id="benton2010---realizability-and-compositional-compiler-correctness-for-a-polymorphic-language"&gt;benton2010 - Realizability and Compositional Compiler Correctness for a Polymorphic Language&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://nickbenton.name/cccmsrtr.pdf"&gt;&amp;ldquo;Realizability and Compositional Compiler Correctness for a Polymorphic Language&amp;rdquo;&lt;/a&gt;, Benton and Hur define a &amp;ldquo;realizability&amp;rdquo; interpretation of System F types realized by terms in low-level language, for proving some compiler correctness properties. The terms realize the types, and this lets us talk about which low-level programs are valid to link with, without restricting the set of linkable programs to only those generated by the compiler.&lt;/p&gt;

&lt;p&gt;This has lost all connection to intuitionistic vs classical logic, but I suppose it keeps the key features of the technique: types (formula) of one language are realized by terms in another, and there is some concern that the realizers should be a subset of all terms. Not all low-level programs should be valid, but some set of them should be.&lt;/p&gt;

&lt;h2 id="nakano2000---a-modality-for-recursion"&gt;nakano2000 - A Modality for Recursion&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://doi.org/10.1109/LICS.2000.855774"&gt;&amp;ldquo;A Modality for Recursion&amp;rdquo;&lt;/a&gt; was actually the start of my realizability journey. This paper starts by defining a collection of models (β-models) of the untyped λ-calculus. It then defines the class of realizability models, in terms of β-models, for an extrinsically typed λ-calculus with equi-recursive types. A realizability model is parameterized by a β-model, and is a relation inductively defined over types to their realizers, which are values drawn from the β-model.&lt;/p&gt;

&lt;p&gt;So why is this realizability? Well, I don&amp;rsquo;t see anything to do with intuitionistic vs classical. But, the set of all values is larger than the set of realizers, which seems to be important to all uses of &amp;ldquo;realizability&amp;rdquo;, and important for this result in particular. In this paper, this is used to show that the dot modality rules out some valid β-model terms, namely those that would correspond to non-terminating λ terms.&lt;/p&gt;

&lt;p&gt;Later in the paper, they define a &amp;ldquo;realizability interpretation&amp;rdquo;. This seems to be distinct from the collection of all realizability models in that they pick a particular set of realizers? So, it ought to be a realizability model, I guess? But they don&amp;rsquo;t say so explicitly. The interpretation is still quite heavily parameterized, but it does seem to fix or restrict the set of realizers. Anyway, this interpretation includes all the features of my definition above: it&amp;rsquo;s inductively defined over types, relating types to (a semantic model of) untyped λ terms, for the purposes of proving something about the collection of realizers as they related to the collection of all untyped λ terms.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">The A Means A</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2022/06/30/the-a-means-a/" />
  <id>urn:https-www-williamjbowman-com:-blog-2022-06-30-the-a-means-a</id>
  <published>2022-06-30T17:25:55Z</published>
  <updated>2022-06-30T17:25:55Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;I have argued about the definition of &amp;ldquo;ANF&amp;rdquo; many times. I have looked at the history and origins, and studied the translation, and spoken to the authors. And yet people insist I&amp;rsquo;m &amp;ldquo;quacking&amp;rdquo; because I insist that &amp;ldquo;ANF&amp;rdquo; means &amp;ldquo;A-normal form&amp;rdquo;, where the &amp;ldquo;A&amp;rdquo; only means &amp;ldquo;A&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Here, I write down the best version of my perspective so far, so I can just point people to it.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;I want to answer three question: what does the &lt;em&gt;A&lt;/em&gt; mean, why does the &lt;em&gt;A&lt;/em&gt; matter, and where does the &lt;em&gt;A&lt;/em&gt; come from.&lt;/p&gt;

&lt;h2 id="what-does-the-a-mean"&gt;What does the &lt;em&gt;A&lt;/em&gt; mean?&lt;/h2&gt;

&lt;p&gt;The &amp;ldquo;A&amp;rdquo; in &amp;ldquo;A-normal form&amp;rdquo; refers to a particular formal object, named &amp;ldquo;A&amp;rdquo; (not &amp;ldquo;administrative&amp;rdquo;), with respect to which there is a normal form with certain useful properties. This form is &amp;ldquo;A normal&amp;rdquo;&amp;mdash;none of the A reductions apply to terms in this form&amp;mdash;hence, A-normal form.&lt;/p&gt;

&lt;p&gt;While it&amp;rsquo;s true that the history of ANF is concerned with &amp;ldquo;administrative reductions&amp;rdquo; &lt;em&gt;in CPS&lt;/em&gt;, this is an informal concept, modeled by the formal object &amp;ldquo;A&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;In truth, &amp;ldquo;A&amp;rdquo; is several formal objects, defined somewhat differently in at least 3 different papers. Only one of these is arguably called &amp;ldquo;administrative&amp;rdquo;, but is about CPS, and not what we now call ANF.&lt;/p&gt;

&lt;p&gt;&amp;ldquo;A&amp;rdquo; appears in &amp;ldquo;The Essence of Compiling with Continuations&amp;rdquo;, page 5. Under the discussion of the CPS, optimization, and un-CPS diagram, the authors observe that this diagram begs for a completion, some direct process, &amp;ldquo;A&amp;rdquo;, that simply normalizes a term within the same language. This diagram is reproduced below: \[
\begin{array}{ccc}
e &amp;amp; \overset{CPS}{\to} &amp;amp; e' \\
\overset{A}{\downarrow} &amp;amp;&amp;amp; \overset{\beta}{\downarrow} \\
e_A &amp;amp; \overset{unCPS}{\leftarrow} &amp;amp; e_O
\end{array}
\] They ask, what are some set of reductions, call this set A, such that normalizing with respect to A would produce a normal form, A-normal form, that characterizes the use of CPS in practice.&lt;/p&gt;

&lt;p&gt;The same pattern appears in "Reasoning about Programs in Continuation-Passing Style, page 1:&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;Thus, we refine this question as follows:  Is there a set of axioms, A, that extend the call-by-value λ-calculus such that: &amp;hellip;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;The authors go on to define the set A, never naming it by &lt;em&gt;some administrative reductions&lt;/em&gt;, but deriving A instead from the inverse CPS translation.&lt;/p&gt;

&lt;p&gt;We could argue that Sabry&amp;rsquo;s thesis, Chapter 3, Section 1, &amp;ldquo;Administrative Source Reduction: The A-Reductions&amp;rdquo;, names the A-reductions &amp;ldquo;administrative&amp;rdquo;. He goes on to analyse those reductions considered to be the administrative ones, defining βlift and βflat in terms of CPS. He then defines in Definition 3.1, the administrative source reduction (A-reductions). However, these refer to reductions over CPS terms, and are distinct from the reductions considered for ANF. While they are the origin of ANF, they do not produce terms in what we now call ANF. A term in &amp;ldquo;administrative normal form&amp;rdquo; with respect to that set of reductions would actually be in CPS. That&amp;rsquo;s not what we mean when we say ANF; we mean normal with respect to the set A defined in &amp;ldquo;The Essence of Compiling with Continuations&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Maintaining this distinction between the formal object A and the informal notion of administrative reductions is important for two reasons. First, it helps remind us that ANF is a form ultimately about normalizing a specific set of reductions, not the output of a particular translation, which is important in practice. Implementations often relax ANF until code generation, by omitting some of the A reductions, typically, A2 in &amp;ldquo;The Essence of Compiling with Continuations&amp;rdquo;&amp;mdash;even that paper relaxes A2 in their implementation in the appendix, because A2 leads to exponential code duplication or requires object-language continuations (&amp;ldquo;join points&amp;rdquo;). It&amp;rsquo;s hard to even formally discuss this relaxation if we do not have the set of normalized reductions in mind. Second, the idea that ANF is free of &amp;ldquo;administrative&amp;rdquo; redexes is absurd, since the idea of the administrative redex is an informal concept: a reduction that isn&amp;rsquo;t really necessary but merely an artifact of the translation. It is easy to introduce such administrative redexes in ANF; e.g., &lt;code&gt;let x = y in
x&lt;/code&gt; contains an extra unnecessary ζ redex, but it is in ANF. It is, however, free of A reductions.&lt;/p&gt;

&lt;h2 id="why-does-the-a-matter"&gt;Why does the &lt;em&gt;A&lt;/em&gt; matter?&lt;/h2&gt;

&lt;p&gt;I don&amp;rsquo;t actually care what the &amp;ldquo;A&amp;rdquo; means, or what the authors intended it to mean. I care that we think about ANF as a normal form, normal with respect to a specific set of reductions.&lt;/p&gt;

&lt;p&gt;This most recent rant was triggered by a conversation with a reviewer, who, after observing that the &amp;ldquo;A&amp;rdquo; actually stood for &amp;ldquo;administrative&amp;rdquo;, asked whether our ANF translation could be decomposed into two translations, one that did everything but normalize the &lt;code&gt;if&lt;/code&gt;s (handling &lt;code&gt;if&lt;/code&gt; is annoying in ANF, as it either requires being clever or causes code duplication), and then separately handle &lt;code&gt;if&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The answer is completely obvious&amp;hellip; if you think about ANF in terms of a normal form with respect to a set of reductions, and not as merely the output of some translation process, nor &amp;ldquo;CPS but like without adminsitrative redexes&amp;rdquo;. Since ANF is a normal form with respect to &amp;ldquo;A&amp;rdquo;, we can easily decompose it into multiple normal forms, thus deriving several decomposed translations: remove the A reduction that normalizes &lt;code&gt;if&lt;/code&gt;, and you get another normal form. Remove the rules that normalize &lt;code&gt;if&lt;/code&gt; and nested &lt;code&gt;let&lt;/code&gt;, and you get monadic form.&lt;/p&gt;

&lt;p&gt;But all of this is much more complicated to explain if you think of ANF as a particular translation or particular syntactic form, and not a normal form with respect to the set A. And this seems to be very likely how you will think of you think &lt;em&gt;A&lt;/em&gt; means &lt;em&gt;administrative&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id="where-does-the-a-come-from"&gt;Where &lt;em&gt;does&lt;/em&gt; the &lt;em&gt;A&lt;/em&gt; come from??&lt;/h2&gt;

&lt;p&gt;Incidentally, I spoke with Amr after he read this blog post. The origin of the &amp;ldquo;A&amp;rdquo; comes from a result by Curry, who proves some theorems about any combinatory logic extended by a set &lt;em&gt;A&lt;/em&gt; of ground equations: https://staff.fnwi.uva.nl/p.h.rodenburg/Varia/RelCLlam.pdf&lt;/p&gt;

&lt;p&gt;This led Matthias to ask Amr to create a set &lt;em&gt;A&lt;/em&gt;, such that bla bla bla.&lt;/p&gt;

&lt;p&gt;Amr admits he may have intended a pun between &lt;em&gt;A&lt;/em&gt; and &lt;em&gt;administrative&lt;/em&gt;, but doesn&amp;rsquo;t remember.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">How I Redex---Experimenting with Languages in Redex</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2019/10/06/how-i-redex-experimenting-with-languages-in-redex/" />
  <id>urn:https-www-williamjbowman-com:-blog-2019-10-06-how-i-redex-experimenting-with-languages-in-redex</id>
  <published>2019-10-06T19:45:13Z</published>
  <updated>2019-10-06T19:45:13Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;Recently, I asked my research assistant, Paulette, to create a Redex model. She had never used Redex, so I pointed her to the usual tutorials:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;a href="https://redex.racket-lang.org/"&gt;https://redex.racket-lang.org/&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://docs.racket-lang.org/redex/tutorial.html"&gt;https://docs.racket-lang.org/redex/tutorial.html&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://docs.racket-lang.org/redex/redex2015.html"&gt;https://docs.racket-lang.org/redex/redex2015.html&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;While she was able to create the model from the tutorials, she was left the question &amp;ldquo;what next?&amp;rdquo;. I realized that the existing tutorials and documentation for Redex do a good job of explaining &lt;em&gt;how&lt;/em&gt; to implement a Redex model, but fail to communicate &lt;em&gt;why&lt;/em&gt; and &lt;em&gt;what&lt;/em&gt; one does with a Redex model.&lt;/p&gt;

&lt;p&gt;I decided to write a tutorial that introduces Redex from the perspective I approach Redex while doing work on language models&amp;mdash;a tool to experiment with language models. The tutorial was originally going to be a blog post, but it ended up quite a bit longer that is reasonable to see in a single page, so I&amp;rsquo;ve published it as a document here:&lt;/p&gt;

&lt;div style="text-align: center"&gt;
 &lt;h3&gt;&lt;a href="/doc/experimenting-with-redex/"&gt;Experimenting with Languages in Redex&lt;/a&gt;&lt;/h3&gt;&lt;/div&gt;</content></entry>
 <entry>
  <title type="text">Untyped Programs Don't Exist</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2018/01/19/untyped-programs-don-t-exist/" />
  <id>urn:https-www-williamjbowman-com:-blog-2018-01-19-untyped-programs-don-t-exist</id>
  <published>2018-01-19T23:37:01Z</published>
  <updated>2018-01-19T23:37:01Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;Lately, I&amp;rsquo;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&amp;rsquo;t exist (although the statement will turn out to be trivial).&lt;/p&gt;

&lt;p&gt;&lt;a id="orgf07fde6"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4 id="tldr"&gt;TLDR&lt;/h4&gt;

&lt;p&gt;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&amp;mdash;&lt;em&gt;e.g.&lt;/em&gt; tools for writing and enforcing invariants about programs&amp;mdash;instead of talking about types and type checking as properties of languages.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;h2 id="table-of-contents"&gt;Table of Contents&lt;/h2&gt;

&lt;div id="table-of-contents"&gt;
 &lt;div id="text-table-of-contents"&gt;
  &lt;ul&gt;
   &lt;li&gt;&lt;a href="#orgf07fde6"&gt;1. TLDR&lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;&lt;a href="#orgaf4345b"&gt;2. Some Context&lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;&lt;a href="#orgdaebb53"&gt;3. Definitions&lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;&lt;a href="#org124f9c8"&gt;4. Is X a Typed Language?&lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;&lt;a href="#org8701978"&gt;5. But I Don't Get Type Errors in X!&lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;&lt;a href="#orgbd43271"&gt;6. Untyped Programs Don't Exist.&lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;&lt;a href="#org53d6b39"&gt;7. Conclusion&lt;/a&gt;&lt;/li&gt;
   &lt;li&gt;&lt;a href="#related"&gt;8. Related Reading&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a id="orgaf4345b"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="some-context"&gt;Some Context&lt;/h2&gt;

&lt;p&gt;In most of my academic work, I work with &amp;ldquo;typed&amp;rdquo; 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.&lt;/p&gt;

&lt;p&gt;When I&amp;rsquo;m hacking, I write in &amp;ldquo;untyped&amp;rdquo; 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.&lt;/p&gt;

&lt;p&gt;&amp;ldquo;But surely&amp;rdquo;, a type evangelist says, &amp;ldquo;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!&amp;rdquo;&lt;/p&gt;

&lt;p&gt;&amp;ldquo;Dear friend, I couldn&amp;rsquo;t agree more!&amp;rdquo;, I reply, "Types are invaluable to developing my programs, but your &amp;lsquo;typed&amp;rsquo; language &lt;strong&gt;prevent&lt;/strong&gt; me from writing down my types!&amp;rsquo;&lt;/p&gt;

&lt;p&gt;"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!"&lt;/p&gt;

&lt;p&gt;"Don&amp;rsquo;t you see,", I say excitedly, "that is just what I&amp;rsquo;m doing! My &amp;lsquo;untyped&amp;rsquo; languages are, in fact, well-typed. My programs run implicitly in the error monad. What&amp;rsquo;s more, I am not required to &lt;strong&gt;prove&lt;/strong&gt; it, for it is simply &lt;strong&gt;true&lt;/strong&gt;."&lt;/p&gt;

&lt;p&gt;A grave look comes over my interlocutor&amp;rsquo;s face. "But you forfeit all benefits of static typing. Your errors are reported later, and there are performance implications, and &amp;#8230;"&lt;/p&gt;

&lt;p&gt;"Exactly.", I interrupt. "We are not arguing about typing, for all programs are well typed. We are arguing about pragmatics."&lt;/p&gt;

&lt;p&gt;&lt;a id="orgdaebb53"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="definitions"&gt;Definitions&lt;/h2&gt;

&lt;p&gt;Before I can argue that untyped programs don&amp;rsquo;t exist, I need some near-formal definitions to work with. I posit the following definitions are reasonable, intuitive definitions about types and programs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definition.&lt;/strong&gt; An &lt;em&gt;expression&lt;/em&gt; is a symbol of sequence of symbols given some interpretation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;code&gt;5&lt;/code&gt; is an expression, whose interpretation is the number five.&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;e₁ + e₁&lt;/code&gt; is an expression, whose interpretation is the mathematical addition function applied to  expressions &lt;code&gt;e₁&lt;/code&gt; and &lt;code&gt;e₂&lt;/code&gt;.&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;function(): return 5;&lt;/code&gt; is an expression, whose interpretation is a mathematical function that  when applied to any number of arguments returns the expression &lt;code&gt;5&lt;/code&gt;.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Definition.&lt;/strong&gt; A &lt;em&gt;type&lt;/em&gt; is a statement of the invariants of some expressions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;a &lt;em&gt;register word&lt;/em&gt; 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:
  &lt;ul&gt;
   &lt;li&gt;move a value of type register word into a register&lt;/li&gt;
   &lt;li&gt;move a value of type register word from one register into another&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
 &lt;li&gt;a &lt;em&gt;pointer&lt;/em&gt; is a type describing a memory address. It is either uninitialized or a valid memory address.  A pointer supports operations such as:
  &lt;ul&gt;
   &lt;li&gt;initialization, giving an uninitialized pointer a value&lt;/li&gt;
   &lt;li&gt;dereference, reading the value of the memory address of an initialized pointer&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
 &lt;li&gt;a &lt;em&gt;Nat&lt;/em&gt; is a type describing an element of the set of natural numbers.  A Nat supports operations such as:
  &lt;ul&gt;
   &lt;li&gt;addition&lt;/li&gt;
   &lt;li&gt;multiplication&lt;/li&gt;
   &lt;li&gt;subtraction, but only when subtracting a smaller natural number from a larger natural number&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Definition.&lt;/strong&gt; A &lt;em&gt;language&lt;/em&gt; is collection of expressions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;arith is a language containing the following expressions &lt;em&gt;e&lt;/em&gt;:
  &lt;ul&gt;
   &lt;li&gt;&lt;code&gt;0&lt;/code&gt;,&lt;code&gt;1&lt;/code&gt;,&lt;code&gt;2&lt;/code&gt; &amp;#8230;, etc and &lt;code&gt;-1&lt;/code&gt;,&lt;code&gt;-2&lt;/code&gt;,&lt;code&gt;-3&lt;/code&gt;, &amp;#8230;, etc, each representing an integer&lt;/li&gt;
   &lt;li&gt;&lt;code&gt;e₁ + e₂&lt;/code&gt;, where &lt;code&gt;e₁&lt;/code&gt; and &lt;code&gt;e₂&lt;/code&gt; are integers&lt;/li&gt;
   &lt;li&gt;&lt;code&gt;e₁ - e₂&lt;/code&gt;, where &lt;code&gt;e₁&lt;/code&gt; and &lt;code&gt;e₂&lt;/code&gt; are integers&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;
 &lt;li&gt;JavaScript is a language, defined by the ECMAScript standard, and extended by various  implementations.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Definition.&lt;/strong&gt; A &lt;em&gt;program&lt;/em&gt; is a collection of expressions from some language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;&lt;code&gt;5 + 5&lt;/code&gt; is an arith program.&lt;/li&gt;
 &lt;li&gt;&lt;code&gt;5&lt;/code&gt; is a JavaScript program.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;&lt;a id="org124f9c8"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="is-x-a-typed-language"&gt;Is X a Typed Language?&lt;/h2&gt;

&lt;p&gt;Is x86 assembly a typed language?&lt;/p&gt;

&lt;p&gt;I say yes.&lt;/p&gt;

&lt;p&gt;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, &lt;code&gt;mov ax, bx&lt;/code&gt; is an x86 assembly program that moves the contents of register &lt;code&gt;bx&lt;/code&gt; to register &lt;code&gt;ax&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Second, x86 is typed. Each expression in x86 assembly has invariants stated about the expression. For example, x86 defines the type &amp;ldquo;little endian&amp;rdquo;, 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).&lt;/p&gt;

&lt;p&gt;I would make the same argument for every other language. C is a typed language. So is JavaScript. And Racket. And Haskell.&lt;/p&gt;

&lt;p&gt;&lt;a id="org8701978"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="but-i-dont-get-type-errors-in-x"&gt;But I Don&amp;rsquo;t Get Type Errors in X!&lt;/h2&gt;

&lt;p&gt;First, you probably do. Second, when you don&amp;rsquo;t, that&amp;rsquo;s a major problem.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;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&amp;rsquo;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.&lt;/p&gt;

&lt;p&gt;Let&amp;rsquo;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 &lt;code&gt;x=e&lt;/code&gt;, where &lt;code&gt;x&lt;/code&gt; is a declared name and &lt;code&gt;e&lt;/code&gt; is an expression. The expression &lt;code&gt;x=e&lt;/code&gt; raises a static error when &lt;code&gt;x&lt;/code&gt; 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, &lt;code&gt;bool b; if(b) { ... };&lt;/code&gt; 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.&lt;/p&gt;

&lt;p&gt;&lt;a id="orgbd43271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="untyped-programs-dont-exist"&gt;Untyped Programs Don&amp;rsquo;t Exist&lt;/h2&gt;

&lt;p&gt;First, a few more definitions based on the above arguments about the languages x86 and C.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definition.&lt;/strong&gt; A &lt;em&gt;type error&lt;/em&gt; is an error raised during the enforcement of a type, &lt;em&gt;i.e.&lt;/em&gt;, during the enforcement of an invariant about an expression.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definition.&lt;/strong&gt; &lt;em&gt;Undefined behavior&lt;/em&gt; is the result of interpreting a non-expression, &lt;em&gt;i.e.&lt;/em&gt;, a sequence of symbols that have no meaning because some invariant has been violated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Theorem.&lt;/strong&gt; Untyped Programs Don&amp;rsquo;t Exist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Proof.&lt;/strong&gt; Recall that programs consist of expressions from a language. Expressions are sequences of symbols that have meaning. But &lt;em&gt;undefined behavior&lt;/em&gt; 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&amp;rsquo;t exist. &lt;strong&gt;QED.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I warned you it was a trivial theorem.&lt;/p&gt;

&lt;p&gt;&lt;a id="org53d6b39"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;The theorem is trivial, but still useful because it helps us reframe our discussion.&lt;/p&gt;

&lt;p&gt;Really, the statement is just a rephrasing of type safety: &amp;ldquo;well typed programs don&amp;rsquo;t go wrong&amp;rdquo;. 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 &lt;em&gt;language&lt;/em&gt;, and in particular, of statically typed languages. We should think about type safety differently: it is a property we must enforce of &lt;em&gt;programs&lt;/em&gt;. 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.&lt;/p&gt;

&lt;p&gt;Instead of arguing about untyped vs typed, a non-existent distinction, we should accept that all programs have invariants that must be obeyed, &lt;em&gt;i.e.&lt;/em&gt;, all programs are typed. The argument we must have is about the pragmatics of types and type checking.&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;how can we express types about complex languages like x86 and C&lt;/li&gt;
 &lt;li&gt;under what situations should we enforce types, &lt;em&gt;i.e.&lt;/em&gt;, check types&lt;/li&gt;
 &lt;li&gt;is type checking useful&lt;/li&gt;
 &lt;li&gt;should we check types statically or dynamically&lt;/li&gt;
 &lt;li&gt;should we allow the programmer to circumvent types checking&lt;/li&gt;
 &lt;li&gt;is type checking decidable&lt;/li&gt;
 &lt;li&gt;should it be&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;&lt;a id="related"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id="related-reading"&gt;Related Reading&lt;/h2&gt;

&lt;h4 id="httpdxdoiorg107146bricsv7i3220167the-meaning-of-types---from-intrinsic-to-extrinsic-semantics-reynold-2000"&gt;&lt;a href="http://dx.doi.org/10.7146/brics.v7i32.20167"&gt;&lt;em&gt;The Meaning of Types - From Intrinsic to Extrinsic Semantics&lt;/em&gt;&lt;/a&gt; (Reynold 2000)&lt;/h4&gt;

&lt;p&gt;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&amp;rsquo;s treat all programs as existing in the universal domain, and  use embedding-projection pairs essentially as contracts at run-time, since, &lt;em&gt;e.g.&lt;/em&gt;, 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 &amp;ldquo;after&amp;rdquo; semantics, the semantics still require  types.&lt;/p&gt;

&lt;h4 id="httpsexistentialtypewordpresscom20110319dynamic-languages-are-static-languagesdynamic-languages-are-static-languages-harper-2011"&gt;&lt;a href="https://existentialtype.wordpress.com/2011/03/19/dynamic-languages-are-static-languages/"&gt;&lt;em&gt;Dynamic Languages are Static Languages&lt;/em&gt;&lt;/a&gt; (Harper 2011)&lt;/h4&gt;

&lt;p&gt;This blog post argues that dynamic languages are just straight-jacketed versions of static  languages, and therefore they aren&amp;rsquo;t really a separate class of languages.  In many ways, I agree with this blog post.  Because &amp;ldquo;dynamic&amp;rdquo; 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 &lt;code&gt;#f&lt;/code&gt; is sometimes used at type &lt;code&gt;bool&lt;/code&gt;  and sometimes at type &lt;code&gt;Maybe A&lt;/code&gt;. This can lead to annoying problems with functions like &lt;code&gt;findf&lt;/code&gt; over  a list of &lt;code&gt;bools&lt;/code&gt;.  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.&lt;/p&gt;

&lt;h4 id="httpsmediumcomsamthon-typed-untyped-and-uni-typed-languages-8a3b4bedf68con-typed-untyped-and-uni-typed-languages-tobin-hochstadt-2014"&gt;&lt;a href="https://medium.com/@samth/on-typed-untyped-and-uni-typed-languages-8a3b4bedf68c"&gt;&lt;em&gt;On Typed, Untyped, and Uni-typed Languages&lt;/em&gt;&lt;/a&gt; (Tobin-Hochstadt 2014)&lt;/h4&gt;

&lt;p&gt;This blog post begins to get at some of the same criticisms of Harper&amp;rsquo;s view, and starts to talk  about pragmatics.&lt;/p&gt;

&lt;h4 id="httpblogsperlorgusersovid201008what-to-know-before-debating-type-systemshtmlwhat-to-know-before-debating-type-systems-smith-2010"&gt;&lt;a href="http://blogs.perl.org/users/ovid/2010/08/what-to-know-before-debating-type-systems.html"&gt;&lt;em&gt;What to Know Before Debating Type Systems&lt;/em&gt;&lt;/a&gt; (Smith 2010)&lt;/h4&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;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"&gt;&lt;a href="https://www2.ccs.neu.edu/racket/pubs/dissertation-felleisen.pdf"&gt;&lt;em&gt;The Calculi of Lambda-v-CS Conversion: A Syntactic Theory of Control and State in Imperative Higher-order Programming Languages&lt;/em&gt;&lt;/a&gt; (Felleisen 1987)&lt;/h4&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h4 id="httphomessoicindianaedujsiekwhat-is-gradual-typingwhat-is-gradual-typing-siek-2014"&gt;&lt;a href="http://homes.soic.indiana.edu/jsiek/what-is-gradual-typing/"&gt;&lt;em&gt;What is Gradual Typing&lt;/em&gt;&lt;/a&gt; (Siek 2014)&lt;/h4&gt;

&lt;p&gt;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 &amp;ldquo;good points&amp;rdquo; in this blog post.  For example, the point &amp;ldquo;Dynamic type checking doesn’t get in your way&amp;rdquo; is a bad point to me;  it&amp;rsquo;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 &lt;code&gt;add1(true)&lt;/code&gt; at the end of the post should be refuted by a gradual type  system, but passes current &amp;ldquo;plausibility checkers&amp;rdquo;, even when &lt;code&gt;add1&lt;/code&gt; has static type annotations  requiring that its argument be a number.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">The reviewers were right to reject my paper</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2017/10/08/the-reviewers-were-right-to-reject-my-paper/" />
  <id>urn:https-www-williamjbowman-com:-blog-2017-10-08-the-reviewers-were-right-to-reject-my-paper</id>
  <published>2017-10-09T03:22:35Z</published>
  <updated>2017-10-09T03:22:35Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;I submitted two papers to POPL 2018. The first, &lt;a href="https://williamjbowman.com/papers#cps-sigma"&gt;&amp;ldquo;Type-Preserving CPS Translation of Σ and Π Types is Not Not Possible&amp;rdquo;&lt;/a&gt;, was accepted. The second, &amp;ldquo;Correctly Closure-Converting Coq and Keeping the Types, Too&amp;rdquo; (draft unavailable), was rejected.&lt;/p&gt;

&lt;p&gt;Initially, I was annoyed about the reviews. I&amp;rsquo;ve since reconsidered the reviews and my work, and think the reviewers were right: this paper needs more work.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;p&gt;In short and in my own words, the reviews criticized my work as follows:&lt;/p&gt;

&lt;ol&gt;
 &lt;li&gt;The translation requires ad-hoc additions to the target language.&lt;/li&gt;
 &lt;li&gt;There is no proof of type soundness of the target language.&lt;/li&gt;
 &lt;li&gt;The work ignores the issue of computational relevance, compiling irrelevant things like functions in Prop.&lt;/li&gt;
 &lt;li&gt;The key insight is poorly explained, lost in the details of the Calculus of Inductive Constructions  (CIC).&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;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&amp;rsquo;re compiling too much, but we&amp;rsquo;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&amp;rsquo;s on me.&lt;/p&gt;

&lt;p&gt;And that&amp;rsquo;s, essentially, what I wrote in my rebuttal. However, now I&amp;rsquo;m reconsidering my position.&lt;/p&gt;

&lt;p&gt;But first, some context.&lt;/p&gt;

&lt;p&gt;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 &lt;a href="https://williamjbowman.com/papers#cccc-popl17-src"&gt;here&lt;/a&gt;. 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&amp;rsquo;t find a great formal description of how to treat &lt;code&gt;Type&lt;/code&gt;; 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&amp;rsquo;d want to compile those into distinct concepts in the long run. So I decided to do CIC since it&amp;rsquo;s a more realistic source, but treat soundness of the target and relevance as future work.&lt;/p&gt;

&lt;p&gt;To judge this work, we have to look at the type-preserving compilation literature. Since the reviews came out, I&amp;rsquo;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 &amp;ldquo;System F to Typed Assembly Language&amp;rdquo;. That work does not compile a realistic programming language; it compiles System F. Essentially it shows how to preserve one feature&amp;mdash;parametric polymorphism&amp;mdash;into a statically typed assembly language. And it took four of the best in our field to do that and do it &lt;em&gt;&amp;ldquo;right&amp;rdquo;&lt;/em&gt;. 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.&lt;/p&gt;

&lt;p&gt;Judged by this standard, I can see the reviewers&amp;rsquo; 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&amp;mdash;full spectrum dependent types&amp;mdash;and doing that &lt;em&gt;right&lt;/em&gt;. 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 &lt;em&gt;right&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So, thank you POPL anonymous reviewers for evaluating my work. You&amp;rsquo;ve given me a new perspective on my work and I think I know how to improve it.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">What even is compiler correctness?</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2017/03/24/what-even-is-compiler-correctness/" />
  <id>urn:https-www-williamjbowman-com:-blog-2017-03-24-what-even-is-compiler-correctness</id>
  <published>2017-03-24T21:41:13Z</published>
  <updated>2017-03-24T21:41:13Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;In this post I precisely define common compiler correctness properties. Compilers correctness properties are often referred to by vague terms such as &amp;ldquo;correctness&amp;rdquo;, &amp;ldquo;compositional correctness&amp;rdquo;, &amp;ldquo;separate compilation&amp;rdquo;, &amp;ldquo;secure compilation&amp;rdquo;, 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.&lt;/p&gt;
&lt;!-- more--&gt;

&lt;h3 id="what-is-a-language"&gt;What is a Language&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;A Language \( \mathcal{L} \) is defined as follows. \[
\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} &amp;amp; P \\
\text{Components} &amp;amp; C \\
\text{Linking Contexts} &amp;amp; \gamma \\
\text{Link Operation} &amp;amp; γ(C) &amp;amp; : &amp;amp; P \\
\text{Program Equivalence} &amp;amp; \peqvsym &amp;amp; : &amp;amp; P \to P \to Prop \\
\text{Linking Equivalence} &amp;amp; \leqvsym &amp;amp; : &amp;amp; \gamma \to \gamma \to Prop \\
\text{Component Equivalence} &amp;amp; \ceqvsym &amp;amp; : &amp;amp; C \to C \to Prop \\
\text{Observational Equivalence} &amp;amp; \ctxeqvsym &amp;amp; : &amp;amp; C \to C \to Prop \\
\end{array}
\] where \(\ctxeqvsym\) is the greatest compatible and adequate equivalence on Components.&lt;/p&gt;

&lt;p&gt;A Language \(\mathcal{L}\) has a notion of Programs \(P\). Programs can be evaluated to produce observations. Program Equivalence \(\peqv{P_1}{P_2}\) defines when two Programs produce the same observations. A Language also has a notion of Components \(C\). 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 \(\gamma\) to a Component \(C\), written \(\gamma(C)\). Linking Contexts can also be compared for equivalence using Linking Equivalence \(\leqv{\gamma_1}{\gamma_2}\). Observational Equivalence is a &amp;ldquo;best&amp;rdquo; notion of when two Components are related. Note, however, that a Language&amp;rsquo;s Observational Equivalence is completely determined by other aspects of the language. We are not free to pick this relation.&lt;/p&gt;

&lt;p&gt;&lt;span class="example"&gt;C is a Language; its definition is as follows. Let \(P\) be any well-defined whole C program that defines a function&lt;code&gt;main&lt;/code&gt;; such a program would produce a valid executable when compiled. Let \(C\) be any well-defined C program that defines a function&lt;code&gt;main&lt;/code&gt;, 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 \(\gamma\) 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.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="example"&gt;Coq (or, CIC) is a Language; its definition is as follows. Let \(P\) be any closed, well-typed Coq expression. Let \(C\) be any open, well-typed Coq expression. Let \(\gamma\) 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.&lt;/span&gt;&lt;/p&gt;

&lt;h3 id="what-is-a-compiler"&gt;What is a Compiler&lt;/h3&gt;

&lt;p&gt;Using our generic definition of Language, we define a generic Compiler as follows.&lt;/p&gt;

&lt;p&gt;\[
\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} &amp;amp; \mathcal{L}_S \\
\text{Target Language} &amp;amp; \mathcal{L}_T \\
\text{Program Translation} &amp;amp; \leadsto &amp;amp; : &amp;amp; P_S \to P_T \\
\text{Component Translation} &amp;amp; \leadsto &amp;amp; : &amp;amp; C_S \to C_T \\
\text{Cross-Language (S/T) Program Equivalence} &amp;amp; \psteqvsym \\
\text{S/T Linking Equivalence} &amp;amp; \lsteqvsym \\
\text{S/T Component Equivalence} &amp;amp; \csteqvsym \\
\end{array}
\]&lt;/p&gt;

&lt;p&gt;Every Compiler has a source Language \(\mathcal{L}_S\) and target Language \(\mathcal{L}_T\). We use the subscript \(_S\) when referring to definition from \(\mathcal{L}_S\) and \(_T\) when referring to definitions from \(\mathcal{L}_T\). Every Compiler defines a translation from \(\mathcal{L}_S\) Programs to \(\mathcal{L}_T\) Programs, and similarly a translation on Components. A Compiler also defines cross-language relations on Programs, Components, and Linking Contexts.&lt;/p&gt;

&lt;p&gt;&lt;span class="example"&gt;We can define a Compiler from C to x86 as follows. Let \(\mathcal{L}_S\) be the Language for C defined earlier. Define a Language for x86 similarly. Let &lt;code&gt;gcc&lt;/code&gt; 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.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="example"&gt;We can define a Compiler from Coq to ML as follows. Let \(\mathcal{L}_S\) 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.&lt;/span&gt;&lt;/p&gt;

&lt;h3 id="what-even-is-compiler-correctness"&gt;What Even is Compiler Correctness&lt;/h3&gt;

&lt;h4 id="type-preservation"&gt;Type Preservation&lt;/h4&gt;

&lt;p&gt;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 &amp;ldquo;Type Preservation&amp;rdquo;. Typically, Type Preservation also connotes that the target language has a non-trivial type system and the compiler is obviously non-trivial.&lt;/p&gt;

&lt;p&gt;&lt;span class="theorem"&gt;Type Preservation (Programs)
  &lt;br /&gt; \( P_S \leadsto P_T \)&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="theorem"&gt;Type Preservation (Components)
  &lt;br /&gt; \(C_S \leadsto C_T \)&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;span class="example"&gt;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 &amp;ldquo;Type Preserving&amp;rdquo;, the academic community may laugh at you.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="example"&gt;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 &amp;ldquo;Type Preserving&amp;rdquo;, the academic community may laugh at you.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="example"&gt;The &lt;a href="http://compcert.inria.fr/"&gt;CompCert&lt;/a&gt; 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.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="example"&gt;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.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="example"&gt;The &lt;a href="https://www.cs.princeton.edu/~dpw/papers/tal-toplas.pdf"&gt;System F-to-TAL&lt;/a&gt; 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&amp;rsquo;s types to be preserved. Even so, type preservation could hold if we compile everything to the trivial TAL program, such as &lt;code&gt;halt[int]&lt;/code&gt;. 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.&lt;/span&gt;&lt;/p&gt;

&lt;h4 id="whole-program-correctness"&gt;Whole-Program Correctness&lt;/h4&gt;

&lt;p&gt;The next definition is what I would intuitively expect of all compilers (that are bug free). A source Program should be compiled to a &amp;ldquo;related&amp;rdquo; target Program. In the literature, this theorem is referred to as &amp;ldquo;Whole-Program Correctness&amp;rdquo; or &amp;ldquo;Semantics Preservation&amp;rdquo;. 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.&lt;/p&gt;

&lt;p&gt;&lt;span class="theorem"&gt;Whole-Program Correctness
  &lt;br /&gt; If \(P_S \leadsto P_T \) then \(\psteqv{P_S}{P_T} \)&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;span class="example"&gt;The &lt;a href="http://compcert.inria.fr/"&gt;CompCert&lt;/a&gt; C-to-Asm compiler is proven correct with respect to Whole-Program Correctness, with machine checked proofs. CompCert refers to this guarantee as &amp;ldquo;semantics preservation&amp;rdquo;. Prior versions of CompCert pointed out that, while it is possible to Link after compilation, &amp;ldquo;the formal guarantees of semantic preservation apply only to whole programs that have been compiled as a whole by CompCert C.&amp;rdquo; More recent versions lift this restrctions, as we discuss shortly.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="example"&gt;The &lt;a href="https://cakeml.org/"&gt;CakeML&lt;/a&gt; CakeML-to-Asm compiler is proven correct with respect to Whole-Program Correctness, with machine checked proofs. CakeML is &amp;ldquo;a substantial subset of SML&amp;rdquo;. Asm is one of several machine languages: ARMv6, ARMv8, x86&amp;ndash;64, MIPS&amp;ndash;64, and RISC-V. The assemblers here, unlike in &lt;a href="http://compcert.inria.fr/"&gt;CompCert&lt;/a&gt;, are proven correct.&lt;/span&gt;&lt;/p&gt;

&lt;h4 id="compositional-correctness"&gt;Compositional Correctness&lt;/h4&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;span class="theorem"&gt;Compositional Correctness
  &lt;br /&gt; If \(C_S \leadsto C_T\) and \(\lsteqv{\gamma_S}{\gamma_T}\) then \(\psteqv{\gamma_S(C_S)}{\gamma_T(C_T)}\)&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The phrase &amp;ldquo;Compositional Correctness&amp;rdquo; usually connotes that the relation \(\lsteqvsym\) is defined independently of the compiler&amp;mdash;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.&lt;/p&gt;

&lt;p&gt;&lt;span class="theorem"&gt;Compositional Compiler Correctness
  &lt;br /&gt; If \(C_S \leadsto C_T\) and \(\lsteqv{\gamma_S}{\gamma_T}\) then \(\psteqv{\gamma_S(C_S)}{\gamma_T(C_T)}\) (where \(\lsteqvsym\) is independent of \(\leadsto\))&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;The phrase &amp;ldquo;Separate Compilation&amp;rdquo; usually connotes that linking is only defined with Linking Contexts produced by same compiler. That is, when \(\lsteqv{\gamma_S}{\gamma_T} \iff \gamma_S \leadsto \gamma_T\).&lt;/p&gt;

&lt;p&gt;&lt;span class="theorem"&gt;Correctness of Separate Compilation
  &lt;br /&gt; If \(C_S \leadsto C_T\) and \(\gamma_S \leadsto \gamma_T\) then \(\psteqv{\gamma_S(C_S)}{\gamma_T(C_T)}\)&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Some papers present a variant of &amp;ldquo;Semantics Preservation&amp;rdquo; 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.&lt;/p&gt;

&lt;p&gt;&lt;span class="theorem"&gt;Semantics Preservation
  &lt;br /&gt; If \(C_S \leadsto C_T \) then \(\csteqv{C_S}{C_T} \)&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;div class="theorem"&gt;Open Compiler Correctness
 &lt;br /&gt; 
 &lt;ol&gt;
  &lt;li&gt;If 
   &lt;script type="math/tex"&gt;C_S \leadsto C_T&lt;/script&gt;, then for all 
   &lt;script type="math/tex"&gt;\gamma_T&lt;/script&gt;, 
   &lt;script type="math/tex"&gt;\psteqv{\gamma_T(C_S)}{\gamma_T(C_T)}&lt;/script&gt;&lt;/li&gt;
  &lt;li&gt;If 
   &lt;script type="math/tex"&gt;C_S \leadsto C_T&lt;/script&gt;, then for all 
   &lt;script type="math/tex"&gt;\gamma_S&lt;/script&gt;, 
   &lt;script type="math/tex"&gt;\psteqv{\gamma_S(C_S)}{\gamma_S(C_T)}&lt;/script&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Some languages, like Coq and Racket, target special purpose VMs and aim only to be Separate Compilers.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;span class="example"&gt;The &lt;a href="https://www.cs.princeton.edu/~appel/papers/compcomp.pdf"&gt;Compositional CompCert&lt;/a&gt; compiler extends &lt;a href="http://compcert.inria.fr/"&gt;CompCert&lt;/a&gt; and its correctness proofs to guarantee Compositional Compiler Correctness. Linking is defined for any target Linking Context whose &lt;em&gt;interaction semantics&lt;/em&gt; are related to a source Linking Context. The paper&amp;rsquo;s Corollary 2 titled &amp;ldquo;Compositional Compiler Correctness&amp;rdquo; 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.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="example"&gt;The &lt;a href="https://people.mpi-sws.org/~viktor/papers/sepcompcert.pdf"&gt;SepCompCert&lt;/a&gt; compiler extends &lt;a href="http://compcert.inria.fr/"&gt;CompCert&lt;/a&gt; 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 &lt;a href="https://github.com/AbsInt/CompCert/releases/tag/v2.7"&gt;version 2.7&lt;/a&gt;.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="example"&gt;The &lt;a href="http://plv.mpi-sws.org/pils/paper.pdf"&gt;Pilsner&lt;/a&gt; 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.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="example"&gt;&lt;a href="http://www.ccs.neu.edu/home/amal/papers/voc.pdf"&gt;Perconti and Ahmed&lt;/a&gt; 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.&lt;/span&gt;&lt;/p&gt;

&lt;h4 id="full-abstractionsecure-compilation"&gt;Full Abstraction/Secure Compilation&lt;/h4&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Fully abstract compilers, seek to prove compilers preserve these relational properties. Since security properties are often relational, these are sometimes called &amp;ldquo;Secure Compilers&amp;rdquo;. Often times, we also want to &lt;em&gt;reflect&lt;/em&gt; equivalence, which usually follows from Compositional Correctness. Full abstraction refers specifically to preserving and reflecting Observational Equivalence. Papers on this topic often focus on equivalence preservation, since equivalence reflection by itself usually follows from compiler correctness, and preservation is the direction of interest for stating security properties.&lt;/p&gt;

&lt;p&gt;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 &amp;ldquo;decompiling&amp;rdquo; a target Program into a source Program.&lt;/p&gt;

&lt;p&gt;&lt;span class="theorem"&gt;Equivalence Preservation
  &lt;br /&gt; If \(\ceqv{C_S}{C'_S}\) and \(C_S \leadsto C_T\) and \(C'_S \leadsto C'_T\) then \(\ceqv{C_T}{C'_T}\)&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="theorem"&gt;Equivalence Reflection
  &lt;br /&gt; If \(\ceqv{C_T}{C'_T}\) and \(C_S \leadsto C_T\) and \(C'_S \leadsto C'_T\) then \(\ceqv{C_S}{C'_S}\)&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="theorem"&gt;Full Abstraction
  &lt;br /&gt; Let \(C_S \leadsto C_T\) and \(C'_S \leadsto C'_T\). \(\ctxeqv{C_S}{C'_S}\) iff \(\ctxeqv{C_T}{C'_T}\)&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="example"&gt;&lt;a href="https://williamjbowman.com/papers/#niforfree"&gt;Bowman and Ahmed&lt;/a&gt; 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.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="example"&gt;&lt;a href="https://www.microsoft.com/en-us/research/wp-content/uploads/2013/01/js-star.pdf"&gt;Fournet et al.&lt;/a&gt; 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.&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="example"&gt;&lt;a href="https://people.mpi-sws.org/~marcopat/marcopat/Publications_files/logrel-for-facomp.pdf"&gt;Devriese et al.&lt;/a&gt; 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.&lt;/span&gt;&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">Toward Type-Preserving Compilation of Coq, at POPL17 SRC</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2017/01/03/toward-type-preserving-compilation-of-coq-at-popl17-src/" />
  <id>urn:https-www-williamjbowman-com:-blog-2017-01-03-toward-type-preserving-compilation-of-coq-at-popl17-src</id>
  <published>2017-01-03T21:41:11Z</published>
  <updated>2017-01-03T21:41:11Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;Almost two months ago, my colleagues in the Northeastern PRL wrote about &lt;a href="http://prl.ccs.neu.edu/blog/2016/11/17/src-submissions/"&gt;three of our POPL 2017 Student Research Competition submissions&lt;/a&gt;. There was fourth submission, but because I was hard at work completing proofs, it wasn&amp;rsquo;t announced.&lt;/p&gt;

&lt;h2 id="toward-type-preserving-compilation-of-coq"&gt;Toward Type-Preserving Compilation of Coq&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://williamjbowman.com/papers#cccc-popl17-src"&gt;Toward Type-Preserving Compilation of Coq&lt;/a&gt;
 &lt;br /&gt; William J. Bowman
 &lt;br /&gt; 2016
 &lt;br /&gt;&lt;/p&gt;

&lt;blockquote&gt;
 &lt;p&gt;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, &lt;a href="http://dx.doi.org/10.1145/268946.268954"&gt;Morrisett &lt;em&gt;et al.&lt;/em&gt; (1998)&lt;/a&gt; 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. &lt;a href="http://doi.acm.org/10.1145/231379.231414"&gt;Tarditi &lt;em&gt;et al.&lt;/em&gt; (1996)&lt;/a&gt; develop a compiler for ML that uses a typed IL for optimizations.&lt;/p&gt;
 &lt;p&gt;We develop type-preserving closure conversion for the Calculus of Constructions (CC). Typed closure conversion has been studied for simply-typed languages (&lt;a href="http://dx.doi.org/10.1145/237721.237791"&gt;Minamide1996&lt;/a&gt;, &lt;a href="https://dl.acm.org/citation.cfm?id=1411227"&gt;Ahmed2008&lt;/a&gt;, &lt;a href="http://doi.acm.org/10.1145/2951913.2951941"&gt;New2016&lt;/a&gt;) and polymorphic languages (&lt;a href="http://dx.doi.org/10.1145/237721.237791"&gt;Minamide1996&lt;/a&gt;, &lt;a href="http://dx.doi.org/10.1145/268946.268954"&gt;Morrisett1998&lt;/a&gt;). Dependent types introduce new challenges to both typed closure conversion in particular and to type preservation proofs in general.&lt;/p&gt;&lt;/blockquote&gt;</content></entry>
 <entry>
  <title type="text">ICFP 2016</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2016/10/15/icfp-2016/" />
  <id>urn:https-www-williamjbowman-com:-blog-2016-10-15-icfp-2016</id>
  <published>2016-10-15T21:15:00Z</published>
  <updated>2016-10-15T21:15:00Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;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.&lt;/p&gt;

&lt;h4 id="tldr"&gt;TLDR&lt;/h4&gt;

&lt;p&gt;I went to ICFP again this year. I&amp;rsquo;m a frequent attendee. Last year I had &lt;a href="/papers/#niforfree"&gt;a paper&lt;/a&gt; and &lt;a href="https://youtu.be/-vgWefEXHt0"&gt;gave a talk&lt;/a&gt;. This year I had &lt;a href="/papers/#fabcc"&gt;a paper&lt;/a&gt;, but someone else gave &lt;a href="https://www.youtube.com/watch?v=Hylji4ezQHE"&gt;the talk&lt;/a&gt;. But I also gave a &lt;a href="http://conf.researchr.org/event/hope-2016/hope-2016-papers-growing-a-proof-assistant"&gt;talk&lt;/a&gt; at HOPE 2016. I met some people and saw some talks and pet a deer.&lt;/p&gt;

&lt;hr /&gt;
&lt;!-- more--&gt;

&lt;p&gt;I&amp;rsquo;m a fifth year Ph.D. candidate studying compiler correctness, dependent types, and (functional) programming language abstractions. ICFP is my second home.&lt;/p&gt;

&lt;p&gt;This year, I met some cool new researchers, several of whose names I&amp;rsquo;ve already forgotten (sorry new friends). I met &lt;a href="https://zoep.github.io/"&gt;Zoe Paraskevopoulou&lt;/a&gt;, 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 &lt;a href="http://pleiad.cl/people/etanter"&gt;Éric Tanter&lt;/a&gt;, who works on, among many things, gradual typing and dependent types. He gave &lt;a href="https://youtu.be/GwmZTGd1rZs"&gt;a talk&lt;/a&gt; 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&amp;rsquo;s also interested in Racket, so we spent some time discussing &lt;a href="/papers/#cur"&gt;Cur&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I got some new ideas for Cur. &lt;a href="http://davidchristiansen.dk/"&gt;David Christiansen&lt;/a&gt;&amp;rsquo;s talk on &lt;a href="https://youtu.be/pqFgYCdiYz4"&gt;Elaborator Reflection: Extending Idris in Idris&lt;/a&gt; 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. &lt;a href="https://distrinet.cs.kuleuven.be/people/jesper"&gt;Jesper Cockx&lt;/a&gt;&amp;rsquo;s talk on &lt;a href="https://youtu.be/TbyAfTCbyHQ"&gt;Unifiers as Equivalences&lt;/a&gt; demonstrated ideas that might let me implement unification as a user defined extension in a proof-relevant way.&lt;/p&gt;

&lt;p&gt;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&amp;rsquo;t properly digest the first time. I hope I finish those by next year.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">Post-ECOOP</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2016/08/10/post-ecoop/" />
  <id>urn:https-www-williamjbowman-com:-blog-2016-08-10-post-ecoop</id>
  <published>2016-08-10T19:46:50Z</published>
  <updated>2016-08-10T19:46:50Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;I returned from ECOOP a few weeks ago, and have been trying to figure out what I got of the experience. I&amp;rsquo;ll focus on two big things.&lt;/p&gt;

&lt;p&gt;For a long time I have been debating what I should do after I graduate, which I usually phrase as &amp;ldquo;industry vs academia&amp;rdquo;. I&amp;rsquo;m coming to understand this is a false dichotomy, as most dichotomies are. (It helps that a friend &lt;a href="https://twitter.com/chckadee/status/761312153370517504"&gt;spelled it out for me&lt;/a&gt;.) Dave Herman&amp;rsquo;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&amp;rsquo;s summer school lectures were equally helpful, and sort of the dual of this: taking objects from industry&amp;mdash;scripting languages&amp;mdash;and applying academic rigor to them. ECOOP, more than any other conference I&amp;rsquo;ve been to, brought together industry and academia in a smooth spectrum. I wish I had attended as a younger student.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;make&lt;/code&gt; and the dynamic linker, etc. Java has Eclipse. Coq has OCaml plugins.  All of these languages require doing &amp;ldquo;more&amp;rdquo; 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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;ECOOP was a great experience. If I go again, though, I hope the summer school won&amp;rsquo;t conflict with the entire research track.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">ECOOP 2016</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2016/07/15/ecoop-2016/" />
  <id>urn:https-www-williamjbowman-com:-blog-2016-07-15-ecoop-2016</id>
  <published>2016-07-15T20:18:06Z</published>
  <updated>2016-07-15T20:18:06Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;Full disclosure: This blog post is sponsored and required by the National Science Foundation (NSF): The NSF! Funding SCIENCE! since 1683 or whenever.&lt;/p&gt;

&lt;h4 id="tldr"&gt;TLDR&lt;/h4&gt;

&lt;p&gt;I&amp;rsquo;m going to ECOOP to see a part of the PL community I wouldn&amp;rsquo;t normally see, talk to people that I wouldn&amp;rsquo;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, &lt;a href="https://williamjbowman.com"&gt;read a little about me&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id="the-long-story"&gt;The long story&lt;/h4&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&amp;ldquo;Huh&amp;rdquo;, I thought to myself, &amp;ldquo;I wonder what&amp;rsquo;s interesting in Rome&amp;rdquo;. I went to the &lt;a href="http://2016.ecoop.org/program/program-ecoop-2016"&gt;ECOOP program&lt;/a&gt; and started looking around.&lt;/p&gt;

&lt;p&gt;The Curry On program looks interesting. This co-located conference should help me understand how PL applies to industry problems. Unfortunately, I&amp;rsquo;m going to miss most or all the first day. But the talk I&amp;rsquo;m most interested in is the final keynote, &amp;ldquo;Building an Open Source Research Lab&amp;rdquo;; hopefully this will give me some insights on this &lt;a href="https://williamjbowman.com/blog/2015/11/02/to-academia-or-not-to-academia"&gt;industry vs academia problem I have been struggling with&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There is also a summer school. While the history of typed and untyped languages looks fascinating, I&amp;rsquo;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 &amp;ldquo;Building a Research Program for Scripting Languages&amp;rdquo; 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&amp;rsquo;m going to learn how to build a JIT compiler for free, because despite being a compilers expert, I don&amp;rsquo;t know anything about JIT compilers. Finally, I&amp;rsquo;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.&lt;/p&gt;

&lt;p&gt;Unfortunately, the summer school is in parallel with most of the conference talks, so it&amp;rsquo;s going to be tough to decide how much of the summer school to miss in order to see new research.&lt;/p&gt;

&lt;p&gt;&amp;ldquo;Yeah&amp;rdquo;, I thought after much consideration, &amp;ldquo;I guess there are some interesting things to see in Rome&amp;rdquo;. I&amp;rsquo;m a little concerned about the accommodations and venue though; I understand that a lot of the architecture in Rome is &lt;em&gt;very&lt;/em&gt; old.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">Conference talks reconsidered</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2015/08/29/conference-talks-reconsidered/" />
  <id>urn:https-www-williamjbowman-com:-blog-2015-08-29-conference-talks-reconsidered</id>
  <published>2015-08-30T04:18:36Z</published>
  <updated>2015-08-30T04:18:36Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;In my earlier post, I point out that the typical advice I hear is &amp;ldquo;The talk should be an ad for the paper&amp;rdquo;. After several discussions, I think this is bad advice. Instead, &lt;a href="http://composition.al/"&gt;Lindsey Kuper&lt;/a&gt; and &lt;a href="https://www.cs.cmu.edu/~cmartens/"&gt;Chris Martens&lt;/a&gt; encouraged me to ignore this advice and instead make my talk a performance.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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 &amp;ldquo;90% perfect&amp;rdquo;, in defiance of a NU PRL tradition of not dwelling on positive aspects and only giving constructive &lt;em&gt;criticism&lt;/em&gt; after a practice talk.&lt;/p&gt;

&lt;p&gt;A video of this talk is &lt;a href="https://youtu.be/-vgWefEXHt0"&gt;online here&lt;/a&gt;.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">Conference talks</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2015/08/08/conference-talks/" />
  <id>urn:https-www-williamjbowman-com:-blog-2015-08-08-conference-talks</id>
  <published>2015-08-08T22:24:06Z</published>
  <updated>2015-08-08T22:24:06Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;I am beginning to hate conference talks. I am in the midst of writing a conference talk for my &lt;a href="/papers#niforfree"&gt;recently accepted paper&lt;/a&gt;. 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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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&amp;mdash;20 minutes, in which a speaker much fit a 12-page paper plus supplementary material?&lt;/p&gt;

&lt;p&gt;&amp;ldquo;No! Obviously as a speaker you must &lt;em&gt;not&lt;/em&gt; 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.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;What silly advice. I hate advertisements. Why should I sit through sessions and sessions of advertisements?&lt;/p&gt;

&lt;p&gt;&amp;ldquo;No! Obviously as an audience member you must &lt;em&gt;not&lt;/em&gt; 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.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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?&lt;/p&gt;

&lt;p&gt;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?&lt;/p&gt;

&lt;p&gt;&amp;ldquo;Well the talks give an excuse and talking points around which we can organize a conference.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;Well why can&amp;rsquo;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?&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;</content></entry>
 <entry>
  <title type="text">Notes on "Ur: Statically-Typed Metaprogramming ..."</title>
  <link rel="alternate" href="https://www.williamjbowman.com/blog/2015/02/14/notes-on-ur-statically-typed-metaprogramming/" />
  <id>urn:https-www-williamjbowman-com:-blog-2015-02-14-notes-on-ur-statically-typed-metaprogramming</id>
  <published>2015-02-14T17:22:11Z</published>
  <updated>2015-02-14T17:22:11Z</updated>
  <author>
   <name>William J. Bowman</name></author>
  <content type="html">
&lt;p&gt;Today I read &lt;a href="http://adam.chlipala.net/papers/UrPLDI10/"&gt;Ur: Statically-Typed Metaprogramming with Type-level Record Computation&lt;/a&gt;. 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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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&amp;rsquo;s macros or Template Haskell.&lt;/p&gt;</content></entry></feed>