<<

arXiv:1908.03619v1 [cs.PL] 9 Aug 2019 09Cprgthl yteowner/author(). the by held Copyright 2019 © langua programming functional new a of design the present We hl hs aiu ak nov h aiuaino synta of manipulation the involve tasks various these While SN978-1-4503-7249-7/19/10. ISBN ACM C eeec Format: ACM etn.Cmo prahsaet mlmn idnsb usi by bindings implement to are program approaches functional Common the setting. within treatments different of range uhntrlsmnisa oia hoywti ihlogi rich a within theory both logical includes a shall as We evaluation. its natural for such s semantics natural abstract a an and MLTS present for we semantics, defin dire formally operational to that order ’s In programs bindings. of within movement sites this support additional includes MLTS of in binders to instead, permitted are : tures their escape nor bindin free approach, become this In . data within appearing the uses that MLTS, https://doi.org/10.1145/3354166.3354177 Portugal Porto, 2019, 7–9, October ’19, PPDP Attributi Commons license. Creative 4.0) the (CC-BY-SA under ternational published is work This an programming all almost binding. of variable feature : key a for provid languages port programming functional earliest these of [ checker proof a for “meta-language” a as designed was programmi ML guage the and parsers, and pro , theorem interpreters, building for logics language common and a languages was Lisp programming example, various manip of that systems the build late to used were func programming, languages high-level programming of days earliest the from Even INTRODUCTION 1 ABSTRACT • CONCEPTS CCS on-l described. An briefly examples. is several MLTS for presenting by MLTS illus of we features and programs the suc ML core a of typing discipl given the typing extends be a naturally present can We presentation. MLTS elegant and of cinct specification semantics natural the ye n structures and types lseGrr,Dl ilr n are cee.21.Functional with 2019. Scherer. ming Gabriel and Miller, Dale Gérard, Ulysse Y S,1 pages. Portugal. 16 Porto, USA, 2019, NY, 7–9, October ’19), (PPDP 2019 guages otaeadisengineering its and Software idnsi ytci xrsin aebe ie,o cours of given, been have expressions syntactic in Bindings λ te ytx In syntax. - oia abstraction nominal https://doi.org/10.1145/3354166.3354177 . λ move -tree ucinlpormigwith programming Functional rnilsadPatc fPormigLan- Programming of Practice and Principles obneswti rgas h design The programs. within binders to ytxapoc oecdn bindings encoding to approach syntax n the and → lseGrr,Dl ilr n are Scherer Gabriel and Miller, Dale Gérard, Ulysse ucinllanguages Functional ∇ -quantifier nSaelk . In- 4.0 ShareAlike on ni I,EoePolytechnique Ecole LIX, & Inria C,NwYork, New ACM, saresult, a as : snever gs program- n that ine ,none x, dsup- ed glan- ng ; aasa,France Palaiseau, tional that c yntax struc- ming the Data view trate For . ctly ,a e, 22]. vers, ine ng ge, u- - 3 on aibe ee eoefe:ised hi bindi their instead, free: become never variables Bound (3) ihisntrlsmnis eto otisafra desc formal a contains 4 Section semantics. natural its with tecr f Ladicroae the incorporates and ML of) core (the [3]. prover theorem Abella aibenmso,i oeasrc a, sn eBuj i Bruijn de using by way, abstract more a in or, names variable λ eso o h ramn fbnig hthsbe successf been has that bindings of treatment the how show We - epeettedsg fMT,anwfntoa agaepro language functional new a MLTS, of design the present We - s nfc,a coy for acronym an fact, in is, a oe hslte ee nrdcstems characteris most the of introduces pect tenet latter This move. can i aeois 2 qaiyo ytxms include must syntax of Equality (2) categories. tic oe rmtepofsac lgcpormig paradigm, programming) w ( design, proof-search MLTS’ the the from of comes to aspects foundational understanding the of working Se some . presents a current and constructs give new its to of reader aims and MLTS guage accessible is that implementation full a MLTS. have of We metatheory the - of some present We - rlg[] wl [46], [6], [43], core reasoning generic Isabelle’s include such binding: to approaches incorporate l that exist of systems imple domains and the designs several In proving, syntax. theorem and in programming bindings wi supporting implemented of and goal designed the been have language, [47] Beluga dependently the as such languages, programming functional entir Also, languages. programming functional ML-style to hr aebe h rsM 5,5]adC and 59] [53, FreshML exa the for before: been considered have been there has data in bindings support aaerchge-re btatsyntax abstract higher-order parametric nomkn ol n irre htcnhl elwt binde with the deal is help there can example, that libraries ri ha and energy get tools of deal making to great into complex a pervasive, quite so are are bindings since techniques and such Since [10]. dexes oigtetretnt:()Sna secdda ipytype simply as encoded is Syntax (1) tenets: three the lowing rey ecndfiethe define can containing we structures Briefly, data of syntax abstract the encoding trsi hc h rmtv ye dnie ihsynta with identified are types primitive the in -terms ttesm ie LSrmisaM-aiylnug;nomi- language; ML-family a remains MLTS time, same the At wl,adAel,cnb noprtdit ucinlpro functional a into incorporated be can Abella, and Twelf, i xrsin n atrs,dsigihn u einf design our distinguishing patterns), and expressions (in asaetetdsmlryt osrcoso leri dat algebraic of constructors to similarly treated are nals language. ming systems proving theorem and programming logic the in oyefrdaigwt idns iiga xrsiiyan expressivity at erality. aiming bindings, with dealing for totype line. sigpooas uha epi n Beluga. and Delphin as such proposals, isting hspprcnan h olwn contributions. following the contains paper This hsppri raie sflos eto nrdcsthe introduces 2 Section follows. as organized is paper This xedn ucinlpormiglnug ihfeatures with language programming functional a Extending nti ae epeetMT,anwlnug htextends that language new a MLTS, present we paper this In λ te ytxwihi fe called often is which syntax -tree λ te syntax -tree oal nameless locally α rlg[] h ilgpoe 5] n the and [57], prover Minlog the [5], Prolog λ oiiyand mobility te ytxapoc osna sfol- as syntax to approach syntax -tree prah[,2,3]adthe and 30] 21, [4, approach λ prah[8]. approach λ te syntax -tree te syntax -tree idrmobility binder α λ L[2 extensions [52] ML rlg[7 0,Qu- 40], [37, Prolog αβη . prahto approach -conversion. gscope ng λ systems l new ely binders. o ex- rom MLTS . ription Prolog, to 3 ction atypes gone s s for rs: gen- d i as- tic typed gram- along mple, mented hich ogic lan- ght that on- th ul n- c- d - PPDP ’19, October 7–9, 2019, Porto, Portugal Ulysse Gérard, Dale Miller, and Gabriel Scherer of the typing system for MLTS as well as some static restrictions we thought of as constructors: as a consequence, we follow the OCaml impose on the language to obtain good reasoning principles. We convention of capitalizing their names. We are assuming that,inall also here some meta-theorems about MLTS. In Section 5 we parts of MLTS, the names of nominals (of bound variables in gen- elaborate on several issues that surround the insertion of binder eral) are not available to programs since α-conversion (the alpha- mobility into this functional . Finally, in betic change of bound variables) is always applicable. Thus, com- Sections 6, 7, and 8 we present future work, related work, and con- pilers are free to implement nominals in any number of ways, even clude. ways in which they do not have, say, print names. We enforce a few restrictions (discussed in Section 4.2) on match 2 A TOUR OF MLTS expressions: Every nab-bounded nominals must occur rigidly (de- We chose the concrete syntax of MLTS to be an extension of that of fined in Section 4.2.3) in the pattern and expressions of the the OCaml programming language (a program in MLTS not using (m @ X1 ... Xj) in patterns are restricted so that m is a pattern the new language features should be accepted by the ocamlc com- variable and X1, ..., Xj are distinct nominals bound within the piler). We assume that the reader is familiar with syntactic scope of the pattern binding on m (which, as a pattern variable, conventions of OCaml [42], many of which are shared with most is scoped outside the scopes of nab-bound nominals and over the ML-like programming languages. whole rule). This restriction is essentially the same as the one re- This section presents the new constructs of MLTS along with a quired by higher-order pattern unification [32]: as a result, pattern set of examples. We also provide a application, TryMLTS [20], matching in this setting is a simple generalization of usual first- that can serve as a companion during the reading of this introduc- order . tion to the language. We note that the (X\ r @ X) is interchangeable with the simple expression r: that is, when r is of => type, η-equality 2.1 The binding features of MLTS holds. We now present two series of examples of MLTS programs. We MLTS contains the following five new language features. hope that the informal presentation given above plus the simplicity (1) Datatypes can be extended to contain new nominal constants of the examples will give a working understanding of the seman- and the (new X in M) program phrase introduces a fresh tics of MLTS. We delay the formal definition of the operational nominal X in the scope of the evaluation of the term M. The semantics of MLTS until Section 3.4. of this expression is the value of M, provided that this value does not contain any remaining occurrence of X – this 2.2 Examples: the untyped λ-calculus would be a nominal escape failure. For example, the term (new X in X) fails during evaluation. The untyped λ-terms can be defined in MLTS as the datatype: (2) A new typing constructor => is used to type bindings within type tm = term structures. This constructor is an addition to the al- | App of tm * tm ready familiar constructor -> used for types. | Abs of tm => tm ;; (3) The (\ as an infix that associates to the The use of the => type constructor here indicates that the argument right) is used to form an abstraction of a nominal over its of Abs is a binding abstraction of a tm over a tm. Notice the absence scope. For example, (X\body) is a syntactic expression that of clause for variables. In MLTS, such a type, called an open type, hides the nominal X in the scope body. Thus the backslash can be extended with a collection of nominal constructors of type introduces an abstraction. tm. Just as the type tm denotes a syntactic category of untyped λ- (4) The infix symbol @ eliminates an abstraction: for example, terms, the type tm => tm denotes the syntactic category of terms the expression ((X\body) @ ) denotes the result of the abstracted over such terms. capture-avoiding substitution of the abstracted nominal X Following usual conventions, expressions whose concrete syn- by the term t in body. The notation (t @ u ) stands for tax have nested binders using the same name are disambiguated by (t @ u @ v) (@ associates to the left). the parser by linking the named variable with the closest binder. (5) Clauses within match-expressions can also contain the (nab Thus, the concrete syntax (Abs(X\ Abs(X\ X))) is parsed as a X in -> t) binding form. Here, X is a nominal local to term α-equivalent to (Abs(Y\ Abs(X\ X))). Similarly, the expres- the clause p -> t. At runtime it will be substituted by a sion (let n = 2 in let n = 3 in n) is parsed as an expression nominal Y from the ambient context that appears in the scrutiny α-equivalent to (let m = 2 in let n = 3 in n): this expression of the match at the same position than X does in p but does has value 3. not already appear in p -> t. The MLTS program in Figure 1 computes the size of an untyped These new term operators have the following precedence from λ-term t. For example, (size (App(Abs(X\X), Abs(X\X)))) - highest to lowest: @, new and \. Other operators have the same uates to 5. In the second match rule, the match-variable r is bound precedences and associativity than in OCaml. Thus the expression to an expression built using the backslash. On the right of that fun r -> X\ new Y in r @ X reads as: fun r -> (X\ (new Y rule, r is applied to a single argument which is a newly provided in (r @ X))). All three binding expressions—(X\body), (new nominal constructor of type tm. The third match rule contains the X in body) and (nab X in rule)—are subject to α-renaming of nab binder that allows the token X to match any nominal: alterna- bound variables, just as the names of variables bound in let decla- tively, that last clause could have matched any non-App and non- rations and function definitions. As we shall see, nominals are best Abs term by using the clause | _ -> 1. (Note that as written, the with λ-tree syntax PPDP ’19, October 7–9, 2019, Porto, Portugal

let rec size t = let rec vacp1 t = match t with match t with | X\X -> false | App(n, m) -> 1 + size n + size m | nab Y in X\ Y -> true | Abs(r) -> 1 + new X in size (r @ X) | X\ App(m @ X, n @ X)-> vacp1 m && vacp1 n | nab X in X -> 1;; | X\ Abs(Y\ r @ X Y) -> new Y in Figure 1: A program for the size of a λ-term. vacp1 (X\ r @ X Y);; let subst t u = new X in let rec vacp2 t = let rec aux t = match t with new X in | X -> u let rec aux term = match term with | nab Y in Y -> Y |X -> false | App(u, v) -> App(aux u, aux v) | nab Y in Y -> true | Abs r -> Abs(Y\ aux (r @ Y)) | App(m, n) -> aux m && aux n in aux (t @ X);; | Abs(u) -> new Y in aux (u @ Y) in aux (t @ X);; let rec beta t = match t with | nab X in X -> X let vacp3 t = match t with |Absr ->Abs(Y\ beta (r @ Y)) | X\s -> true | App(m, n) -> | _ -> false ;; let m = beta m in let n = beta n in begin Figure 3: Three for determining if an ab- match m with straction is vacuous. | Abs r -> beta (subst r n) let rec assoc x alist = match alist with | _ -> App(m, n) | ((u,y)::alst) -> if (u = x) then y else end ;; (assoc x alst);;

let two = Abs(F\ Abs(X\ App(F, App(F, X))));; type tm' = let plus = Abs(M\ Abs(N\ Abs(F\ Abs(X\ | App' of tm' * tm' App(App(M,F), App(App(N,F),X))))));; | Abs' of tm ' => tm';; let times = Abs(M\ Abs(N\ Abs(F\ Abs(X\ App(App(M, App(N, F)), X)))));; let rec id gamma term = match term with Figure 2: The function that computes the substitution [t/x]u | App(m,n) -> App'(id gamma m,id gamma n) and the (partial) function that computes the β-normal form | Abs(r) -> new X in Abs'(Y\ (id ((X,Y)::gamma) (r @ X))) of its argument. | nab X in X -> assoc X gamma;; Figure 4: Translating from tm to its mirror version tm'. three match rules used to define size could have been listed in any order.) The following sequence of expressions shows the evolution of a involving the size function. size (Abs (X\ (Abs (Y\ (App(X,Y))))));; abstraction type => into the ->. Substitution is then 1 + new X in size (Abs (Y\ (App(X,Y))));; used by the second function of Figure 2, beta, to compute the β- 1 + new X in 1 + new Y in size (App(X,Y));; normal form of a given term of type tm. This figure also contains 1 + new X in 1 + new Y in 1 + size X + size Y;; the Church numeral for 2 and operations for addition and multipli- 1 + new X in 1 + new Y in 1 + 1 + 1;; cation on Church numerals. In the resulting evaluation context, the The first call to size binds the pattern variable r to X\ Abs(Y\ values computed by (beta (App(App(plus, two), two))) and App(X,Y)). It is important to note that the names of bound vari- (beta (App(App(times, two), two))) are both the Church nu- ables within MLTS programs and data structures are fictions: in meral for 4. the expressions above, binding names are chosen for . For another example, consider a program that returns true if Figure 2 defines the function (subst t u) that takes an abstrac- and only if its argument, of type tm => tm, is such that its top- tion over terms t and a term u and returns the result of substitut- level bound variable is a vacuous binding (i.e., the bound variable ing the (top-level) bound variable of t with u. This function works is not free in its scope). Figure 3 contains three implementations by first introducing a new nominal X and then defining an auxil- of this boolean-valued function. The first implementation proceeds iary function that replaces that nominal in a term with the term by matching patterns with the prefix X\, thereby, matching expres- u. Finally, that auxiliary function is called on the expression (t sions of type tm => tm. The second implementation uses a differ- @ X) which is the result of “moving” the top-level bound variable ent style: it creates a new nominal X and proceeds to work on the in t to the binding occurrence of the expression new X in. (As term t @ X, in the same fashion as the size example. The internal we note in Section 5.3, such binder movement can sometimes be aux function is then defined to search for occurrences of X in that implemented in constant time.) This substitution function has the term. The third implementation, vacp3, is not (overtly) recursive type (tm => tm) -> (tm -> tm): that is, it is used to inject the since the entire effort of checking for the vacuous binding is done PPDP ’19, October 7–9, 2019, Porto, Portugal Ulysse Gérard, Dale Miller, and Gabriel Scherer

type deb = let rec maptm fapp fabs fvar term = | Dapp of deb * deb match term with | Dabs of deb | App(m,n) -> fapp (maptm fapp fabs fvar m) | Dvar of int;; (maptm fapp fabs fvar n) | Abs(r) -> fabs ( fun x -> let rec nth n l = match (n, l) with match x with | (0, x::) -> x | nab X in X -> | (c, x::k) -> nth (c - 1) k;; maptm fapp fabs fvar (r @ X)) | nab X in X -> fvar X;; let index x l = let rec aux c x k = match (x, k) with let mapvar fvar term = | nab X in (X, X::(l @ X)) -> c maptm (fun m -> fun n -> App(m, n)) | nab X Y in (X, Y::(l @ X Y)) -> (fun r -> Abs(X\ r X)) aux (c + 1) x (l @ X Y) fvar term;; in aux 0 x l;; let lookup sub var = match var with let rec trans prefix term = match term with | nab X in X -> | App(m, n) -> Dapp(trans prefix m, let rec aux s = match s with trans prefix n) |[] ->X |Absr -> new X in | (X,t)::sub -> t Dabs(trans (X::prefix) (r @ X)) | (y,t)::sub -> aux sub | nab Y in Y -> Dvar (index Y prefix);; in aux sub;;

let rec dtrans prefix term = match term with | Dapp(m, n) -> App(dtrans prefix m, let rec remove x l = match l with dtrans prefix n) |[] ->[] | Dabs r -> Abs(X\ dtrans (X::prefix) r) | h::tl -> if h = x then remove x tl | Dvar c -> nth c prefix;; else h::(remove x tl);;

Figure 5: De Bruijn’s style syntax and its conversions with let fv term = type tm. maptm union ( fun r -> new X in remove X (r X)) ( fun x -> x::[]) term;; during pattern matching. The first match rule of this third imple- let size term = maptm (fun x -> fun y ->1 + x+ y) mentation is essentially asking the question: is there an instantia- (fun r -> new X in 1 + (r X)) . tion for the (pattern) variable s so that the λX s equals t? This ques- (fun x -> 1) term;; tion can be posed as asking if the logical formula ∃s.(λX .s) = t can be proved. In this latter form, it should be clear that since substitu- let terminals term = tion is intended as a logical operation, the result of substituting for maptm (fun x -> fun y -> x + y) s never allows for variable capture. Hence, every instance of the (fun r -> new X in (r X)) existential quantifier yields an equation with a left-hand side that (fun x -> 1) term;; is a vacuous abstraction. Of course, this of pattern matching Figure 6: Various on untyped λ-terms using requires a recursive analysis of the term t and that can pat- higher-order programs. Note that there are several occur- tern matching costly. To address that cost, pattern matching can rences of (r X) above that should not be written as (r @ X). be restricted so that such patterns do not occur (see Section 6) or static checks can be added that often make such recursive descents unnecessary (see Section 5.3). functions nth and index take a list of nominals as their second ar- th For another simple example of computing on the untyped λ- gument: nth takes also an integer n and returns the n nominal calculus, consider introducing a mirror version of tm, as is done in that list while index takes a nominal and returns its ordinal po- in Figure 4, and writing the function that constructs the mirror sition in that list. For example, the value of term in tm' from an input term tm. This computation is achieved trans [] (Abs(X\ Abs(Y\ Abs(Z\ App(X,Z)))));; by adding a context (an association list) as an extra argument that is the term Dabs(Dabs(Dabs(Dapp(Dvar 2, Dvar 0)))) of type maintains the association of bound variables of type tm and those deb. If dtrans [] is applied to this second term, the former term of type tm'. The value of id [] (Abs(X\ Abs(Y\ App(X,Y)))) is is returned (modulo α-renaming, of course). (Abs'(X\ Abs'(Y\ App'(X,Y)))) (the types of X and Y in these two expressions are, of course, different). 2.3 Examples: Higher-order programming Figure 5 presents a datatype for the untyped λ-calculus in De Bruijn’s style [10] as well as the functions that can convert be- Recall the familiar higher-order function “fold-right”. tween that syntax and the one with explicit bindings. The auxiliary let rec foldr f a lst = match lst with Functional programming with λ-tree syntax PPDP ’19, October 7–9, 2019, Porto, Portugal

| [] -> a for them directly: for example, any built-in notion of equality or | x :: -> f x (foldr f a xs);; matching should respect at least α-conversion. (The paper [36] con- This function can be viewed as replacing all occurrences of :: with tains an extended argument of this point in the setting of logic pro- the binary function f and all occurrences of [] with a. The higher- gramming and proof assistants.) Another reason to include binders order program maptm in Figure 6 does the analogous operation on as a primitive within a functional programming languages is that the datatype of untyped λ-terms tm. In particular, the constructors their semantics have a well understood declarative and operational App and Abs are replaced by functions fapp and fabs, respectively. treatment. For example, Church’s higher-order logic STT [9] con- In addition, the function fvar is applied to all nominals encoun- tains an elegant integration of bindings in both terms and formulas. tered in the term. This higher-order function can be used to de- His logic also identifies equality for both terms and formulas with fine a number of other useful and familiar functions. For example, αβη-conversion. Church’s integration is also a popular one in theo- mapvar function is a specialization of the maptm function that just rem proving—being the core logic of the Isabelle [44], HOL [23, 25], applies a given function to all nominals in an untyped λ-term. The and Abella [3] theorem provers—as well as the application of a substitution (an expression of type (tm * tm) language λProlog [37]. Given the existence of these provers, a good list)toatermoftype tm can then be seen as the result of applying literature now exists that describes how to effectively implement the lookup function to every variable in the term (using mapvar). STT and closely related logics. Since the formal specifications of Using the functions in Figure 6, the three expressions evaluation and typing will be given using inference rules and since such rules can be viewed as quantified formulas, this literature pro- Abs(X\ mapvar ( fun x -> X) vides means for implementing MLTS. (Abs(U\ Abs(V\ App(U,V)))));; new X in new Y in lookup ((X,Abs(U\U)):: (Y, Abs(U\ App(U,U)))::[]) X;; 3.1 Equality modulo α, β, η conversion new X in new Y in lookup ((X,Abs(U\U)):: The abstract syntax behind MLTS is essentially a simply typed λ- (Y, Abs(U\ App(U,U)))::[]) Y;; term that encodes untyped λ-calculus, as described in Section 3.4. evaluate to the following three λ-terms. Furthermore, the equality theory of such terms is given by the fa- miliar α, β, η conversion rules. As a result, a programming lan- Abs(X\ Abs(Y\ Abs(Z\ App(X, X)))) guage that adopts this notion of equality cannot take an abstrac- Abs(X\ X) tion and return, say, the name of its bound variable: since that Abs(X\ App(X, X)) name can be changed via the α-conversion, such an operation would Three additional functions are defined in Figure 6: fv constructs not be a proper function. Thus, it is not possible to decompose the the list of free variables in a term; size is a re-implementation of untyped λ-term λx.t into the two components x and t. Not being the size function presented in Section 2.2; and terminals counts able to a bound variable’s name might appear as a serious the number of variable occurrences (terminal nodes) in its argu- deficiency but, in fact, it can be a valuable feature of the language: ment. for example, a does not need to maintain such names and can choose any number of different, low-level representations 2.4 Current prototype implementation of bindings to exploit during . Since the names of bind- We have a prototype implementation of MLTS. A parser from our ings seldom have semantically meaningful value, dropping them extended OCaml syntax and a transpiler that generates λProlog entirely is an interesting design choice. That choice is similar to code are implemented in OCaml. A simple evaluator and type checker one taken in ML-style languages in which the location in memory written in λProlog are used to type-check and execute the gener- of a reference cell is not maintained as a value in the language. ated MLTS code. The implementation of the evaluator in λProlog is The relation of λ-conversion is invoked when evaluating the rather compact but not completely trivial since the natural seman- expression (t @ s1 ... sn). As we shall see, MLTS is a typed tics of MLTS (presented in Section 3.4) contains features (namely, language so we can assume that the expressions s1,..., sn have ∇-quantification and nominal abstraction) that are not native to types γ1,...,γn, respectively, and that t must have type γ1 ⇒ λProlog: they needed to be implemented. Both the Teyjus [54] and ··· ⇒ γn ⇒ γ0. Thus, t is η-equivalent to a term with n abstrac- the Elpi [12] implementations of λPrologcan beusedtoexecutethe tions, for example, X1\...Xn\ t' and the value of the expression MLTS interpreter. Since Elpi, the parser, and the transpiler are writ- (t @ s1 ... sn) is the result of performing λ-normalization of ten in OCaml, web-based execution was made possible by compil- ((X1\...Xn\ t') s1 ... sn). ing the OCaml to a Javascript client with js_of_ocaml [27]. There is little about this prototype implementation that is fo- 3.2 Match rule quantification cused on providing an efficient implementation of MLTS. Instead, Match rules in MLTS contain two kinds of quantification. The fa- the prototype is useful for exploring the exact meaning and possi- miliar quantification of pattern variables can be interpreted as be- ble uses of the new program features. ing universal quantifiers. For example, the first rule defining the size function in Section 2.2, namely, 3 THE LOGICAL FOUNDATIONS OF A | App(n, m) -> 1 + size n + size m SEMANTIC DEFINITION OF MLTS can be encoded as the logical statement Bindings are such an intimate part of the nature of syntax that we should expect that our high-level programming languages account ∀m∀n[(size (App(n, m))) = 1 + size n + size m]. PPDP ’19, October 7–9, 2019, Porto, Portugal Ulysse Gérard, Dale Miller, and Gabriel Scherer

The third match rule for size contains the binder nab hold while those in the second row do not.

λx.x D c λx.p x c D p c c λx.λy.p x y D p c c | nab X in X -> 1 1 2 1 2 1 2 λx.x 6D p c1 c2 λx.p x c2 6D p c2 c1 λx.λy.p x y 6D p c1 c1 which corresponds approximately to the generic ∇-quantifier (pro- A logic with equality generalized to nominal abstraction has nounced nabla) that is found in various efforts to formalize the been studied in [16, 18] where a logic, named G, that contains fixed metatheory of computational systems (see [3, 39] and Section 3.4). points, induction, coinduction, ∇-quantification, and nominal ab- . = That is, this rule can be encoded as ∇x (size x 1): that is, the straction is given a sequent calculus presentation. Cut-elimination size of a nominal constant is 1. for G is proved in [16, 18] and and implementations for Although there are two kinds of quantifiers around such match nominal abstraction are presented in [16, 60]. An important fea- rules, the ones corresponding to the universal quantifiers are im- ture of the Abella prover—∇ in the head of a definition—can be plicit in the concrete syntax while the ones corresponding to the explained and encoded using nominal abstraction [17]. ∇-quantifiers are explicit. Our design for MLTS places the implicit quantifiers at outermost scope: that is, the quantification over a 3.4 Natural semantics specification of MLTS match rule is of the form ∀∇. Another choice might be to allow some (all) universal quantifiers to be explicitly written and placed We can now define the of MLTS by giving among any nab bindings. While this is a sensible choice, the ∀∇- inference rules in the style of natural semantics (a.k.a. big-step prefixes is, in fact, a reduction class in the sense that if one has semantics) following Kahn [28]. The semantic definition for the a ∀ quantifier inside a ∇-quantifier, it is possible to rotate that ∇- core of MLTS is defined in Figure 7. Since those inference rules are quantifier inside using a technique called raising [32, 39]. That is, written using a higher-order abstract syntax for MLTS, directly in- the formula ∇x : γ ∀y : τ(Bxy) is logically equivalent to the for- spired by λProlog term representations; we briefly describe how mula ∀h : (γ → τ)∇x : γ (Bx(hx)): note that as the ∇-quantifier of that abstract syntax is derived from the concrete syntax. type γ is moved to the right over a universal quantifier, the type Instead of detailing the translation from concrete to abstract of that quantifier is raised from τ to γ → τ. Thus, it is possible for syntax, we illustrate this translation with an example. There is an an arbitrary mixing of ∀ and ∇ quantifiers to be simplified to be of implementation of MLTS that includes a parser and a transpiler the form ∀∇. into λProlog code: this system is available for online use and for download at https://trymlts.github.io [20]. For example, the λProlog code in Figure 8 is the abstract syntax for the MLTS program for 3.3 Nominal abstraction size given in Section 2.2. Before we can present the formal operational semantics of MLTS, The backslash (as infix notation) is also used in λProlog to de- we need to introduce one final logical concept, nominal abstrac- note binders and it is the only λProlog primitive in Figure 8. The tion, which allows implicit bindings represented by nominals to other constructors are introduced to encode MLTS abstract syntax be moved into explicit abstractions over terms [18]. The following trees. notation is useful for defining this relationship. This encoding of MLTS syntax is a generalization of the famil- Let t be a term, let c1,...,cn be distinct nominals that possibly iar semantic encoding of the untyped λ-calculus given by Scott occur in t, and let y1,...,yn be distinct variables not occurring in t in 1970 [58], in which a semantic domain D and two continuous and such that, for 1 ≤ i ≤ n, yi and ci have the same type. Then we mappings (retracts) Φ: D → (D → D) (encoding application) ′ ′ write λc1 ... λcn.t to denote the term λy1 ... λyn.t where t is the and Ψ: (D → D) → D (encoding abstraction) are used to en- term obtained from t by replacing ci by yi for1 ≤ i ≤ n. There is an code the untyped λ-calculus. For example, the untyped λ-calculus in this notation in that the choice of variables y1,...,yn λxλy((xy)y) is encoded as a value in domain D using the expres- is not fixed. This ambiguity is, however, harmless since the terms sion (Ψ(λx(Ψ(λy(Φ(Φx y)y)))))). In Figure 8, the constructors c_App that are produced by acceptable choices are all equivalent under and c_Abs represents the Φ and Ψ functions, respectively. The λProlog α-conversion. abstraction operator (backslash) is used to build expressions that Let n ≥ 0 and let s and t be terms of type τ1 →···→ τn → τ correspond to inhabitants of D → D. and τ, respectively; notice, in particular, that s takes n arguments The constant fix represents anonymous fixpoints, to which re- to a term of the same type as t. The formula s D t is a nomi- cursive functions are translated (we also have an n-ary fixpoint for nal abstraction of degree n (or, simply, a nominal abstraction). The mutually-recursive functions). Note that fix x \ t is idiomatic symbol D is overloaded since it can be use at different degrees (gen- λProlog syntax for the application fix (x \ t), omitting paren- erally, the degree can be determined from context). The nominal theses to use fix in the style of a binder. abstraction s D t of degree n is said to hold just in the case that s is The expression lam x \ ... represents the MLTS expression λ-convertible to λc1 ... cn .t for some distinct nominals c1,..., cn. fun x -> ...; in our abstract syntax we write lam(λX .... ). (We Clearly, nominal abstraction of degree 0 is the same as equality do not make a syntactic distinction between X and x which are between terms based on λ-conversion, and we will use = to denote just variables, but we use uppercase variables in the abstract syn- this relation in that case. In the more general case, the term on the tax for variables that represent nominals in the language.) Simi- left of the operator serves as a pattern for isolating occurrences of larly, the expression new X \ ... encodes new X in ...; in our nominals. For example, if p is a binary constructor and c1 and c2 abstract syntax we write new (λX .... ). The expression-former are nominals, then the nominal abstractions of the first row below match represents pattern-matching, it expects a scrutinee and a Functional programming with λ-tree syntax PPDP ’19, October 7–9, 2019, Porto, Portugal

values V ::= X ⊢ ∀i ∈[1;n], Ti ⇓ Vi ⊢∇X .(EX) ⇓ V | lam(λx.M x) ⊢ lam R ⇓ lam R ⊢ variant c [T1,...,Tn] ⇓ variant c [V1,...,Vn] ⊢ new (λX .EX) ⇓ V | backslash (λX .V X) | variant c [V1,...,Vn]

⊢ M ⇓ lam R ⊢ N ⇓ U ⊢(R U ) ⇓ V ⊢ M ⇓ U ⊢(R U ) ⇓ V ⊢ R (fix R) ⇓ V ⊢ M ⇓ backslash R ⊢(RX) ⇓ V ⊢ app M N ⇓ V ⊢(let M R) ⇓ V ⊢ fix R ⇓ V ⊢ arobase MX ⇓ V

⊢∇X .(EX)⇓(V X) ⊢ clause T Rule U ⊢ U ⇓ V ⊢ ¬(∃u, clause T Ruleu) ⊢(match T Rules) ⇓ V ⊢ backslash (λX .EX) ⇓ backslash (λX .VX) ⊢(match T (Rule::Rules)) ⇓ V ⊢(match T (Rule::Rules)) ⇓ V

⊢ ∃x.clause T (P x) U ⊢ matches T P ⊢(λZ1 ... λZm .(p =⇒ u)) D (P =⇒ U ) ⊢ clause T (all (λx.P x)) U ⊢ clause T (nab Z1 ... nab Zm .(p =⇒ u)) U

⊢ ∀i ∈[1;n], matches ti pi nominal(c) ⊢ matches (variant c [t1,...,tn ]) (pvariant c [p1,...,pn]) ⊢ matches c (pnom c) ⊢ matches x (pvar x) Figure 7: A natural semantics specification of evaluation.

(fix size \ lam term \ Figure 7 starts with a grammar for values. In addition to lambda- match term abstractions, backslash -expressions (with a value as the body) and [(all m \ all n \ variant values, (open) values also include nominals. Evaluating a (pvariant c_App [(pvar n), (pvar m)]) ==> closed term can never produce a nominal, but evaluation rules un- (special add [(special add [(int 1), der binders may return nominals. (app size n)]), In the rules for app, let and fix, a variable of type 0 → 0 (app size m)])), 0 (all r \ (pvariant c_Abs [pvar r]) ==> (namely, R) is applied to a term of arity type . These rules make (special add use of the underlying equality theory of simply typed λ-terms in [(int 1), G to perform a substitution. In the rule for , for example, if R (new X \ app size is instantiated to the term λw.t and U is instantiated by the term s, (arobase r X))])), then the expression written as (R U ) is equal (in G) to the result of (nab X \ (pnom X) ==> (int 1))]) substituting s for the free occurrences of w in t: that is, to the re- Figure 8: The abstract syntax of the size program. sultof a β-reduction on the expression ((λw.t) s). (While matching and applying patterns is limited to β0-reduction, full β-reduction is used for the natural semantic specification.) Existential quantification is written explicitly into the first rule list of clauses. Clauses are built from the infix operator ==>, tak- for patterns. We write it explicitly here to highlight the fact that ing a pattern on the left and a term on the right, and from quanti- solving the problem of finding instances of pattern variables in fiers all, to introduce universally-quantified variables (implicit in matching rules is lifted to the general problem of finding substi- MLTS programs), and nab to introduce nominals. all-bound vari- tution terms in G. ables and nab-bound nominals have the type of expressions; they The proof rules for natural semantics are nondeterministic in are injected in patterns by pvar and pnom. pvariant (in patterns) principle. Consider attempting to prove that t, a term of arity type and variant (in expressions) denote datatype constructor applica- 0, has a value: that is, ∃V , t ⇓ V . It can be the case that no proof tions, they expect a datatype constructor and a list of arguments. exists or that there might be several proofs with different values special expects the name of a run-time primitive (arithmetic op- for V . No proofs are possible if, for example, the condition in a erations, polymorphic equality...) and a list of arguments. int rep- conditional phrase does not evaluate to a boolean or if there are resents integer literals. Finally, we use explicit AST expression- insufficient match rules provided to cover all the possible values formers backslash and arobase (a French name for @) and pattern- given to a match expression. Ultimately, we will want to provide formers pbackslash and parobase to represent the constructions a static check that could issue a warning if the rules listed in a \ and @ of MLTS. Only arobase is present in this example. match expression are not exhaustive. Conversely, the variables in- It is intended that the inference rules given in Figure 7 are, in troduced by all and nab in patterns may have several satisfying fact, notations for formulas in the logic G. For example, schema values, if they are not used in the pattern itself, or only in flexible variables of the inference rules are universally quantified around occurrences (see Section 4.2.3). the intended formula; the horizontal line is an implication; the list The nominal abstraction of G is directly invoked to solve pattern of premises is a conjunction; and ⇓ is a binary (infix) predicate, etc. matching in which nominals are explicitly abstracted using the nab Some features of G are exploited by some of those inference rules: binding construction. When attempting to prove the judgment ⊢ those features are enumerated below. clause T Rule U , the inference rules in Figure 7 eventually lead PPDP ’19, October 7–9, 2019, Porto, Portugal Ulysse Gérard, Dale Miller, and Gabriel Scherer to an attempt to prove in G an existentially quantified nominal and nominals to type expressions. (We also assume that the order abstraction of the form of pairs in Γ is not important.) The first of these judgments is the usual typing judgment between a program expression M and A. The ∃x ... ∃xn [(λZ ... λZm .(p =⇒ u)) D (P =⇒ U )]. 1 1 second of these judgments is used to type a clause R that has a left- Here, the =⇒ is simply a formal (syntactic) pairing operator, hand side of type A and a right-hand side of type B. For example, expecting a pattern on the left and a term on the right. The schema the following typing judgment should be provable. variables x1,..., xn can appear free only in p and u. Γ tm Abs(r) -> 1 + (new X in size (r @ X)) int The last ingredient of our pattern-matching rule is the judg- ⊢ : : ment (⊢ matches T P) that checks that a term or value T is indeed Since this rule expression is intended to be closed (that is, the vari- matched by a pattern P. Since patterns and terms are encoded us- able r is quantified implicitly around this rule), the actual value of Γ ing two distinct syntactic categories, this judgment relates pattern- will not impact this particular typing judgment. The third typing formers to the corresponding term-formers. Nominals are embed- judgment above is used to analyze the left-hand-side of a match ded in patterns by the pnom(c) pattern-former, which matches a rule: in particular, Γ ⊢ M : A ⊣ ∆ holds if during the process of an- corresponding nominal—the condition nominal(c) can be expressed alyzing the pattern M, pattern variables are produced (since these in terms of nominal abstraction (λX . X) D c. Term variables intro- are implicitly quantified) and placed into the typing context ∆. For duced by all are embedded in patterns by the pvar pattern-former, example, the following should be provable. and they can match any term x—note that in this rule, x denotes an Γ arbitrary term, substituted for a term variable by the all-handling ⊢ Abs(r) : tm ⊣{r : tm => tm} rule. Some of the inference rules in Figure 9 contain premises of the It is worth pointing out that given the way we have defined form (open A) where A is a primitive type. Types for which this the operational semantics of MLTS, it is immediate that “nominals judgment holds are called open types and are the types of bindings cannot escape their scopes.” For example, the expression (new X in the new and backslash expressions: equivalently, open types can in X) does not have a value (in abstract syntax, this expression contain nominals. For our purposes here, we can assume that ev- translates to new (λX .X)). More precisely, there is no proof of ery type that is defined in a program (using the type ) is ∃ ⊢ v.(new (λX .X)) ⇓ v using the rules in Figure 7. To see why presumed to be open. For example, the judgment (open tm) needs this is an immediate consequence of the specification of evalua- to be true so that the type tm => tm can be formed in the various tion, consider the formula (which encodes the rule in Figure 7 for typing rules. On the other hand, the built-in type for integers int new) should not be considered open in this sense. Clearly a keyword ∀E∀V [(∇X .(EX) ⇓ V )⊃(new E ⇓ V )]. must be added to datatype declarations to indicate if a type is in- Given that the scope of the ∇X is inside the scope of ∀V , it is not tended as open in this sense. possible for any instance of this formula to allow the X binder to In the inference rules in Figure 9, whenever we extend the typ- appear as the second argument of the ⇓ predicate. While such es- ing context Γ to, say, Γ, X : A, we assume that X is not declared caping is easily ruled out using this logical specification, a direct in Γ already. Since α-conversion is always possible within terms, implementation of this logic may incur a cost, however, to con- this assumption can always be satisfied. Note that since pattern stantly ensure that no escaping is permitted. (See Section 5.2 for variables are restricted (as is usual) so that they have at most one more discussion on this point.) occurrence in a given pattern, the union of contexts, in the form ∆1,..., ∆n never attributes more than one type to the same vari- 4 TYPING RULES AND RESTRICTIONS, able. SMALL-STEP SEMANTICS, The prototype implementation TryMLTS [20] of MLTS contains META-THEOREMS a engine that runs on top of λProlog: given the - pothetical judgments available in λProlog, the implemented typing In this section we present a typing discipline for MLTS, followed by system is structured differently (but equivalently) to the one given a few restrictions on pattern matching necessary for it to remain in Figure 9. By using λProlog, we were able to turn this typing sys- well behaved and the establishment of standard formal results. tem into one that does type inference: this type inference engine does not infer polymorphic typing, however. 4.1 Typing Given that MLTS is a rather mild extension of OCaml at the syntax 4.2 Restriction on matching level, a typing system for MLTS is simple to present and follows Since we are not able to decompose bindings into their bound vari- standard practices. Figure 9 contains the rules for typing the new able and body, we need to find alternative means for analyzing the features of MLTS: additional rules for encoding let and let rec of terms containing bindings. As our earlier examples il- constructions (as well as for built-in types such as integers) must lustrated, matching within patterns can be used to probe terms and also be added, but these follow the usual pattern. The inference their bindings. If we do not place restrictions on the use of pattern rules in this figure involve the following typing judgments. variables, then patterns can have complex behaviors that we may Γ ⊢ M : A Γ ⊢ A : R : B Γ ⊢ M : A ⊣ ∆ open A wish to avoid during evaluation. In all of these rules, Γ is the usual association between bound vari- 4.2.1 Unique occurrence of paern variables. We impose a familiar ables and a type: in our situation, Γ will associate both variables restriction on the match rules: a pattern variable must have exactly Functional programming with λ-tree syntax PPDP ’19, October 7–9, 2019, Porto, Portugal

Γ ⊢ M : A -> B Γ ⊢ N : A Γ, x : A ⊢ M : B Γ ⊢ M : A Γ, x : A ⊢ M : B Γ, X : A ⊢ M : B open A Γ, x : C ⊢ x : C Γ ⊢ (M N) : B Γ ⊢ (fun x -> M) : A -> B Γ ⊢ let x = M in N : B Γ ⊢ (X \ M) : A => B

Γ ⊢ r : A1 => ... => An => A Γ ⊢ t1 : A1 ... Γ ⊢ tn : An C : A1,..., An → B Γ ⊢ t1 : A1 ... Γ ⊢ tn : An Γ ⊢ (r @ t1 ... tn) : A Γ ⊢ C(t1,...,tn) : B

Γ ⊢ M : A Γ ⊢ N : B Γ, X : A ⊢ M : B open A Γ ⊢ term : B Γ ⊢ B : R1 : A ... Γ ⊢ B : Rn : A Γ ⊢ (M, N) : A * B Γ ⊢ (new X in M) : B Γ ⊢ match term with R1 | ... | Rn : A

Γ, X : C ⊢ A : R : B open C Γ ⊢ L : A ⊣ ∆ Γ, ∆ ⊢ R : B Γ ⊢ X1 : A1 ... Γ ⊢ Xn : An open A1 ... open An Γ ⊢ A : nab X in R : B Γ ⊢ A : L -> R : B Γ ⊢ (r @ X1 ... Xn) : A ⊣ r : A1 => ... => An => A

Γ ⊢ p : A ⊣ ∆1 Γ ⊢ q : B ⊣ ∆2 C : A1,..., An → B Γ ⊢ p1 : A1 ⊣ ∆1 ... Γ ⊢ pn : An ⊣ ∆n Γ ⊢ x : A ⊣ x : A Γ ⊢ (p,q) : A * B ⊣ ∆1, ∆2 Γ ⊢ C(p1,...,pn) : B ⊣ ∆1,..., ∆n Figure 9: Typing rules based on the concrete syntax for the new features of MLTS. one occurrence within a match pattern. Asking for at least one otherwise, undesirable features of higher-order matching could ap- occurrence avoids under-specified pattern variables, that could be pear. Fortunately, there is a natural restriction on occurrences of bound to anything. As is typical in ML-style languages, asking for pattern variables that guarantees that a match either fails or suc- at most one occurrence relieves pattern matching from the need to ceeds with at most one solution. That restriction is the following: check equality of terms. Since terms can be large, pattern match- every occurrence of an expression of the form (r @ X1 ... Xn) ing could involve a costly recursive descent of terms; we forbid in the left-hand side of a match rule must be such that the pattern repeated occurrences of pattern variables and force the program- variable r is applied to n ≥ 0 distinct nominals X1 ... Xn and mer to insert equality checking outside the pattern matching oper- those nominals are bound within the scope of the binding for r. ation. Thus, instead of defining memb : tm -> tm list -> bool For example, the following expression is not well formed with the following code using a repeated match variable Abs(X\ ( match Abs(Y\ App(X,Y)) with let rec memb x l = match (x,l) with | Abs(Z\ r @ Z X) -> |(x,[]) -> false Abs(Z\ r @ X Z)));; | (x,(x::l)) -> true since the scope of the nominal X contains the (implicit) scope of | (y,(x::l)) -> memb x l;; the pattern variable r, which is around the rule (Abs(Z\ r @ Z we can require the to write an equality predicate for X) -> Abs(Z\ r @ X Z)). type tm and then the program above as follows. This restriction can be motivated within a purely logical setting as follows. Let be a primitive type and let F : j → j → j be a let rec eqtm t s = match (t,s) with simply typed constant. The formula ∃g : j → j ∀X : j [g X = | (App(m1,m2), App(n1,n2)) -> eqtm m1 n1 && (FXX)] has a unique proof in which g is instantiated by the term eqtm m2 n2 λW .(F W W ). Note that the binding scope of the variable X is inside | (Abs r, Abs s) -> new X in eqtm (r @ X) (s @ X) the binding scope of the variable g. If, however, one switches the ∀ ∃ = | nab X in (X, X) -> true order of the quantifiers, yielding X : j g : j → j [gX (FXX)], |_ -> false;; then there are four different proofs of this equation: if one replaces the outermost universal quantifier with an eigenvariable (or nom- let rec memb x l = match (x,l) with inal), say A, then there are four different solutions for g, namely, |(x,[]) -> false λW .(F AA), λW .(F A W ), λW .(FW A), and λW .(F W W ). | (x,(y::l)) -> if (eqtm x y) The subset of higher-order unification in which unification vari- then true else (memb x l);; ables (a.k.a., logic variables, meta-variables, pattern variables) are Given the definition of the tm datatype, it is clear that a compiler for applied to distinct bound variables restricted as described above, MLTS could define its own equality predicate for this type. In that is called higher-order pattern unification or Lλ unification [32]. (We case, repeated variable occurrences in patterns could be allowed assume here the usual convention that unification problems and since resolving such patterns could be done using these equality matching problems only involve terms that are in β-normal form.) predicates. This particular subset of higher-order unification is commonly im- plemented in theorem provers such as Abella [3], Minlog [57], and 4.2.2 Restricted use of higher-order paern variables. Since pat- Twelf [46] as well as recent implementations of λProlog [12, 54]. tern variables within match rules can have higher-order types, oc- A functional programming implementation of such unification is currences of those variables within patterns need to be restricted: given in [41]. PPDP ’19, October 7–9, 2019, Porto, Portugal Ulysse Gérard, Dale Miller, and Gabriel Scherer

The following results about higher-order pattern unification are evaluation contexts proved in [32]. E[] ::=  | app M E | app EN (1) It is decidable and unitary, meaning that if there is a unifier | backslash (λX .E) | arobase EX then there exists a most general unifier. | new (λx.E) (2) It does not depend on typing. As a result, it is possible to | variant c [M ... Mk , E, Mk+ ... Mn] add it to the evaluator for MLTS based on untyped terms. 1 2 | match E [R ,..., Rn ] (3) The only form of β-conversion that is needed to solve such 1 unification problems is what is called β0-conversion which is a form of the β rule that equates (λx.t)x with t. app (lam R) V hd RV arobase (backslash R) X hd RX An equivalent way to write the β -conversion rule (assuming 0 hd ′ < the presence of α-conversion) is that (λx.t)y converts to t[y/x] M M X V fix R hd R (fix R) E[M] E[M ′] E[new (λX .V )] E[V ] provided that y is not free in λx.t. Notice that applying β0 reduc- tion actually makes a term smaller and does not introduce new β Figure 11: Small step reduction: core fragment redexes: as a result it is not a surprise that such unification (and, hence, matching) has low computational complexity. namely, using the terms X\Y\X and X\Y\Y. This breaks the deter- 4.2.3 All nab bound variables must have a rigid occurrence. There minacy – Theorem 4.3. In the second example, the nom- is an additional restriction on match rules that is associated to the inal X is completely unconstrained by the pattern. If this program nab binder that appear in such rules. We say that an occurrence was allowed, our natural semantics dictates that it should behave of a nab-quantified nominal is flexible if it is in the scope of an as new X in t; the restriction guarantees that new is the only lan- @. For example, in the code in Figure 10, the nominal binding W guage that may introduce dynamic nominal-escape fail- has two occurrences that are flexible: one each within (r @ Z ures. W) and (r @ W Z). All other occurrences of a nab-bound nominal are rigid. For example, in the match rule | nab X in X -> 1, X 4.3 Small-step operational semantics has a binding occurrence and a rigid occurrence. In the auxiliary As a complement to the natural (big-step) semantics of Figure 7, function used by the index function in Figure 5, namely, we developed a -step operational semantics of MLTS. Its two let rec aux c x k = match (x, k) with salient features are as follows: (1) the small-step treatment of evalu- | nab X in (X, X::(l @ X)) -> c ation contexts clarifies the moments during reduction where escape- | nab X Y in (X, Y::(l @ X Y)) -> checking must be performed (this is often left implicit in the natu- aux (c + 1) x (l @ X Y) ral semantics), and (2) its treatment of pattern-matching does not use nominal-abstraction – it implements an equivalent but lower- the nominals X and Y have both rigid and flexible occurrences within level mechanism. This lower-level expression of the handling of their scope. nabla-bound nominals in pattern-matching gives a more opera- The one additional restriction that we need is the following: ev- tional intuition of the language, and it also guides practical imple- ery nab-bound variable must have at least one rigid occurrence in mentations in languages without native support for nominal ab- the left part of the match rule (the pattern) that falls within the straction. In fact, we co-evolved this operational semantics with scope of its binder. For example, the code in Figure 10 does not the λProlog implementation of the language, the former guiding satisfy this restriction since every occurrence of W in the pattern is the latter, with the bugs found playing with the latter informing flexible (there is just one such occurrence). changes to the former – using the natural semantics as a reference This restriction ensures that each nab-bound nominal in a match- specification for what the behavior should be. ing clause is mapped to a uniquely-determined nominal of the am- Due to space restrictions, we will not give a fully detailed ex- bient context. As interesting counter-examples, consider planation of this operational semantics. For the details, the figures match Z with will have to speak for themselves, we will below give a high-level | nab X Y in (r @ X Y) -> term presentation of the rules. where Z is a nominal, and Core language (without pattern-matching). Figure 11 gives a small- match 1 with step operational semantics for the fragment of the language with- | nab X in 1 -> t out pattern-matching. We use the standard approach of decompos- ing reduction into a head reduction and evaluation contexts. which are both ruled out by this restriction. In the first example, Our evaluation contexts allow reduction under the nominal ab- there are two instantiations for r that make this match succeed, straction (backslash (λX .E) is an evaluation context): it does not delay computation like the standard λ-abstraction does. Abs(X\ ( match Abs(Y\ App(X,Y)) with The other non-standard aspect of this fragment is the treatment | nab W in Abs(Z\ r @ Z W) -> of the name-creation construct new (λX .M). Instead of trying to Abs(Z\ r @ W Z)));; “generate a fresh nominal” in the small-step semantics, we simply Figure 10: Code that does not satisfy the restriction on oc- allow reduction under new binders – the stack of new in the cur- currences of nab bound variables. rent evaluation context is the set of “ambient nominals” available Functional programming with λ-tree syntax PPDP ’19, October 7–9, 2019, Porto, Portugal

rigid paths V with R ∅, N ∄N . (V with R ∅, N ) =  π :: match V (R::Rs) hd N match V (R::Rs) hd match V Rs | variant C i π | backslash (λX .π) Matching a value against a clause: V with R σ, N | arobase π X X ∈π RX Y < R X Y < σ ′ ∇X . ∃π, Y . Rigid occurrence in a value: V ∈π V Y ∈π V V with R Y σ, N

′ V with nab R σ, N V ∈π Vk V ′ ∈ V ′  ′ . , V ∈(variant C k π ) variant c [V1,...,Vn] ∇x V with R σ[x 7→ Vx ] N x V matches p as σ V with (all R) σ, NVx V with (p → N ) σ, N ∇X . V ′ ∈π V ′ V ∈(backslash (λX .π )) (backslash (λX .V )) Matching a value against a pattern: V matches p as σ

V ′ ∈π backslash (λX .V ) ∇X . V X matches pX as σ ′ V ∈(arobase π X ) V backslash V matches backslash p as σ backslash V matches p as σ Rigid occurrence in a pattern: p′ ∈π p V X matches arobase pX as σ ′ ∈π ′ ′ p pk ∀i ∈ 1..n, Vi matches pi as σi p ∈ p ′ p ∈ C k π variant c [p1,...,pn] (variant ) C(V1 ...Vn) matches C(p1 ... pn) as Òi σi

∇X . p′ ∈π p ′ V matches x as (x 7→ V ) V matches _ as ∅ X matches X as ∅ p ∈ λX .π (backslash (λX .p)) (backslash ( )) Figure 13: Small step reduction: pattern-matching p′ ∈π p ′ p ∈(arobase π X ) (arobase pX) not a value, but any value V X can be eta-expanded to the (non- Rigid occurrence in a clause: p′ ∈π R value) form (arobase (backslash λX .V X) X), so we look for the sub-value at path π in (backslash λX .V X). ∇Z. p′ ∈π R ∇x. p′ ∈π R x p′ ∈π p p′ ∈π nab (λZ.R) p′ ∈π all R p′ ∈π p → M Operationalsemantics of pattern matching. The treatment of pattern- matching in this operational semantics, given in Figure 13 is not Figure 12: Rigid paths in values and patterns particularly small-step: matching a value against a clause is a sin- gle step, so it is more big-step in nature. The key interest of these rules is that they do not use nominal abstraction, and instead “im- at this point of the program execution. In addition to the standard plement” the same behavior in a more computational style. rule allowing reduction under context, we have an extra contex- The judgment (v matches p as σ) holds when the value v can tual rule to allow popping a new binder off the context: when the be matched against the value p, by performing the substitution σ – term inside that binder has been fully evaluated to a value, so we from pattern variables in p into sub-values of v. The inputs of the have a term of the form E[new (λX .V )], we can remove the binder judgment are v and p, and the substitution σ is an output of the after performing an escape check (X < V ), continuing evaluation inference process. with E[V ]. If the escape check fails, the term is stuck – this is the The judgment (v with R ∅, N ) holds when the value v can presentation in our semantics of nominal escape as a dynamic fail- be matched against the clause R, returning a right-hand-side N ure. to evaluate. In N , the pattern variables bound in R (by the clause- former all (λx.R)) have already been substituted with the corre- Paths of rigid occurrences. As we explained in Section 4.2.3, a sponding sub-values of v. In the general case, we want to define clause of the form nab (λX .p → M) is only accepted if the nominal the meaning of matching a value v against a clause R after having X has at least one rigid occurrence in the patternp. The operational traversed some all-quantifications, that is with extra pattern vari- semantics uses this criterion. In Figure 12, we define a grammar of ables in the ambient context; the general form of the judgment is rigid paths π, which represent evidence that a given occurrence of v with R σ, N , where σ is a substitution from those ambient a sub-pattern (sub-value) in a pattern (value) is in rigid position, as pattern variables, which still occur free in N . defined by the judgments p′ ∈π p and v ′ ∈π v. The correspondence with the natural semantics is as follows: Looking at the path (arobase π X) in a pattern (arobase p X) v with R σ, N in the operational semantics holds if and only if selects a sub-value by looking at π in p. In terms, (arobase vX) is clause v R[σ] N [σ] holds in the natural semantics. PPDP ’19, October 7–9, 2019, Porto, Portugal Ulysse Gérard, Dale Miller, and Gabriel Scherer

4.4 Formal properties of MLTS better to view such processing as the movement of a binder: that Given the restrictions of Section 4.2, we can list the following three is, the binder in a actually gets re-identified with an formal properties about MLTS. actual binder in the programming language. As we illustrated in Section 2.2 with the following step-by-step evaluation Theorem 4.1 (Nominals do not escape). Let E be the abstract syntax of an MLTS program that does not contain any free nominal. size (Abs (X\ (Abs (Y\ (App(X,Y))))));; If ⊢ E ⇓ V is provable then V does not contain any free nominals. new X in 1 + size (Abs (Y\ (App(X,Y))));; new X in 1 + new Y in 1 + size (App(X,Y));; The proof of this follows from a simple induction on the struc- new X in 1 + new Y in 1 + 1 + size X + size Y;; ture of proofs in the logic G: the precise nature of the semantic new X in 1 + new Y in 1 + 1 + 1 + 1;; specification given in Figure 7 is not relevant. The systematic use the bound variable occurrences for X and Y simply move. It is never of the ∇-quantifier guarantees this conclusion. the case that a bound variable becomes free: instead, it just be- Theorem 4.2 (Type preservation). If the typing judgment ⊢ E : comes bound elsewhere. A and the evaluation judgment ⊢ E ⇓ V holds, then so does ⊢ V : A. The proof is mostly standard, but it must handle the pattern- 5.1 β0 versus β matching rule defined by nominal abstraction. This is done us- As we describe in Section 4.2.2, we insist that in the left sideofa ing our rigid paths π. We can easily prove that if the judgment match rule, all subexpressions of the form (r @ X1 ... Xn) are clause V nab (λZ1.... nab (λZn .p → N )) holds, then the path πi such that the scope of the binding for r contains the scopes of the of Zi in p is also the path of some nominal Yi in v. Then one needs bindings for the distinct variables in X1, ..., Xn. On the right-hand an intermediate lemma to say that the type A of a value or pattern side of a match rule, however, it seems that one has an interesting and a path π within that value or pattern uniquely determine the choice. If on the right, we have an expression of the form (r @ type B of the sub-value or the sub-pattern; because p and v have t1 ... tn) then clearly, the terms t1, ..., tn are intended to be the same type, the nominals Zi and Yi must also have the same substituted into the abstraction that is instantiated for the pattern type, which is key to the type-preservation argument. variable r: that is, we need to use β-conversion on this redex. One design choice is that we restrict the terms t1, ..., tn to be distinct Theorem 4.3 (Determinacy of evaluation). If ⊢ E ⇓ V and nominals just as on the left-hand-side: in this case, β-reduction of ⊢ E ⇓ U then V = U . the expression (r @ t1 ... tn) requires only β0 reductions. A The proof of this theorem follows the usual outline. Again, rigid second choice is that we allow the terms t1, ..., tn to be unre- paths are used in the pattern-matching rule to justify that the nom- stricted: in this case, β-reduction of the expression (r @ t1 ... inals bound by nabla-abstraction are uniquely determined. tn) requires more general (and costly) β-reductions. Our current Detailed proofs of these theorems can be found in the forthcom- implementation allows for these richer forms of @ expressions. ing Ph.D. dissertation of the first author [19]. A similar trade-off between allowing β-conversion or just β0 conversion has also been studied within the theory and design of 5 BINDER MOBILITY the π-calculus. In particular, the full π-calculus allows the substitu- We started this programming language project with the desire to tion of arbitrary names into input prefixes (modeled by β-conversion) treat binders in syntax as directly and naturally as possible. We ap- while the πI -calculus (π-calculus with internal mobility [55]) is re- proached this project by designing the MLTS language with more stricted in such a way that the only instances of β-conversions are, binders than, say, OCaml: it has not only the usual binders for build- in fact, β0-conversions (see Chapter 11 in [37]). ing functions and for refactoring computation (via the let con- Another reason to identify the β0 fragment of β-conversion is struction) but also new binders that are directly linked to binders in that β0 reduction provides support for binder mobility and it can data (via the new X in, nab X in, and X\ operators). Finally, the be given effective implementations, sometimes involving only con- natural semantics of MLTS in G and its implementation in λProlog stant time operations (see Section 5.3). are all based on using logics that contain rich binding operators that go beyond the usual universal and existential quantifiers. It 5.2 Nominal-escape checking is worth noting that if one were to write MLTS programs that do As we have mentioned in Section 3.4, nominals are not allowed not need to manipulate data structures containing bindings, then to escape their scope during evaluation and quantifier alternation the new binding features of MLTS would not be needed and nei- can be used to enforce this restriction at the logic level. When one ther would the novel features of both G and λProlog. Thus, in a implements the logic, one needs to implement (parts of) the unifica- sense, binders have not been formally implemented in this story: tion of simply typed λ-terms [26] and such unification is constantly instead, binders of one kind have been implemented and specified checking that bound variable scopes are properly restricted. There using binders in another system. We were able to complete a proto- are times, however, when the expensive check for escaping nomi- type implementation of MLTS since the implementers of λProlog nals are not, in fact, needed. In particular, it is possible to rewrite provide a low-level implementation of bindings that we are able to the inference rule in Figure 7 for the new binding operator as the use in our static and dynamic semantics specifications. following rule. One way to view the processing of a binder is that one first opens the abstraction, processes the result (by “freshening” the freed names), ⊢∇X .(EX)⇓(U x) U = λX .V and then closes the abstraction [52]. In the setting of MLTS, it is ⊢ new E ⇓ V Functional programming with λ-tree syntax PPDP ’19, October 7–9, 2019, Porto, Portugal

Here, bothU andV are quantified universally around the inference construction. A more effective implementation is also something rule. Attempting a proof of the first premise can result in the con- we wish to target soon. It seems likely that we will need to consider struction of some (possibly large) value, say t, such that ⊢(EX) ⇓ t extensions to the usual abstract models for functional pro- holds. We can immediately form the binding of U 7→ λX .t without gramming in order to get such a direct implementation. A first step checking the structure of t. The second premise is where the exam- in this direction would be to first design a small-step (SOS) seman- ination of t may need to take place: if X is free in t, then there is no tics equivalent of our natural semantics. substitution for V that makes λX .t equal to λX .V . This check can The cost of basic operations in MLTS must also be understood be expensive, of course, since one might in principle need to ex- better. As we noted in Section 2.2, we could design pattern match- amine the entire structure of t to solve this second premise. There ing in clauses in such a way that they might require the recursive are many situations, however, where such an examination is not descent of entire terms in order to know if a match was successful. needed and they can be revealed by the . For example, The language could also be designed so that such a costly check is if the type of U is, say, tm => int, there should not be any pos- never performed during pattern matching: for example, one could sible way for an untyped λ-term to have an occurrence inside an insist that every pattern variable is @-applied to a list of all nomi- integer. Furthermore, there are static methods for examining type nal abstractions that are in the scope of the binding for that pattern declarations in order to describe if a type τ1 → τ2 (for primitive variable. In that case, a recursive descent of terms is not needed. types τ1 and τ2) can be inhabited by at most vacuous λ-terms (see, Given the additional expressivity of MLTS, the usual static checks for example, [33]). Of course, if the types of τ1 and τ2 are the same used to produce warnings for non-exhaustive matchings are miss- (say, tm), then type information is not useful here and a check of ing cases that we should add. As mentioned in Section 5, still other the entire structure t might be necessary. Other static checks and static checks are needed to help a future compiler avoid making program analyses might be possible as a way to reduce the costs costly checks. Finally, adding polymorphic typing should be possi- of checking for escaping nominals: the paper [53] includes such ble following the pattern already established by OCaml. static checks albeit for a technically different functional program- It is also interesting to see to what extent binders interact with ming language, namely FreshML [59]. a range of non-functional features, such as . A natural starting point to explore the possible interaction of effectful fea- 5.3 Costs of moving binders tures would be to use a natural semantics treatment based on lin- As we have mentioned before, binders are able to move from, say, ear logic (see, for example, [7, 34]): the logical features of G should a term-level binding to a program-level binding by the use of β0. In also work well in a linear logic setting. particular, if y is a binder that does not appear free in the abstrac- Finally, the treatment of syntax with bindings generally leads tion λx.B then the β0 reduction of (λx.B)y causes the x binding in to the need to manipulate contexts and association lists that relate B to move and to be identified with the y binder in B[y/x]. If one bindings to other bindings, to types, or to bits of code. We have must actually do the substitution of y for x in B, a possibly large already seen association lists used in Figure 4. It seems likely that term (at least its spine) must be copied. However, there are some more sophisticated MLTS examples will require singling out con- situations where this movement of a binding can be inexpensive. texts for special treatment. Although the current design of MLTS For example, consider again the following match rule for size. does not commit to any special treatment of context, we are inter- ested to see what kind of treatment will actually prove useful in a | Abs(r) -> 1 + ( new X in size (r @ X)) range of applications. If we assume that the underlying implementation of terms use De Bruijn’s indexes, it is possible to understand the rewriting needed 7 RELATED WORK in applying this match clause to be a constant time operation. In particular, if r is instantiated with an abstraction then its top-level The term higher-order abstract syntax (HOAS) wasintroducedin [45] constructor would indicate where a binder of value 0 points. If we to describe an encoding technique available in λProlog. A subse- were to compile the syntax (r @ X) as simply meaning that that quent paper identified HOAS as a technique “whereby variables of top-level constant is stripped away, then a binder of value 0 in the an are mapped to variables in the ” [46]. resulting term would automatically point (move) to being bound When applied to functional programming, this description implies by the new X binder. While such a treatment of binder mobility the mapping of bindings in syntax to the bindings that create func- without doing substitution is possible in many of our examples, it tions. Unfortunately, such encoding technique often lacks adequacy does not cover all cases. In general, a more involved scheme for (since “exotic terms” can appear [11]), and structural can implementing binder mobility must be considered. This kind of slip away [15]. The terms λ-tree syntax [36, 38] and binder mobil- analysis and implementation of binder mobility is used in the ELPI ity [35] were later introduced to describe the different and more implementation of λProlog [12]. syntactic approach that we have used here.

6 FUTURE WORK 7.1 Systems with two arrow type constructors There is clearly much more work to do. While the examples pre- The MLλ [31] extension to ML is similar to MLTS in that it also sented in this paper illustrate that the new features in MLTS can contains two different arrow type constructors (-> and =>) and provide elegant and direct support for computing with binding pattern matching was extended to allow for pattern variables to structures, we plan to develop many more examples centered on be applied to a list of distinct bound variables. The new operator of the general area of implementing theorem provers and compiler MLTS could be emulated by using the backslash operator and the PPDP ’19, October 7–9, 2019, Porto, Portugal Ulysse Gérard, Dale Miller, and Gabriel Scherer

“discharge” function of MLλ. Critically missing from that language programming and not directly reasoning: the intent of the new was anything similar to the nab binding of MLTS. Also, no formal features of MLTS is only to support the manipulation of syntax specification and no implementation were ever offered. Licata & containing bindings. A possibly interesting comparison between Harper [29] have used the universe feature of Agda 2 to provide MLTS and Beluga might be explored by using typing and contexts an implementation of bindings in data structures that also relies in the latter in a mostly trivial way. It is likely that Beluga could on supporting two different implications-as-types. code most MLTS programs although using different primitives. Nominals and nominal abstraction, in the sense used in this pa- per, were first conceived, studied, and implemented as part of the 7.3 Systems using nominal logic Abella theorem prover [3]. While Abella only has one arrow type The FreshML [59] and CαML [52] functional programming lan- constructor, that arrow type maps to the => of MLTS: this is pos- guages provide an approach to names based on nominal logic [48]. sible in Abella since computation is performed at the level of rela- These two programming languages provide for an abstract treat- tions and not functions. As a result, the function type arrow -> of ment of names and naming. Once naming is available, binding MLTS and OCaml is not needed. Thus the distinction mentioned structures can also be implemented. In a sense, the design of these in [29] between an arrow for computation and an arrow for bind- two ML-variants are also more ambitious than the design goal in- ing is, in fact, also present in Abella, although computations are tended for MLTS: in the latter, we were not focused on naming but not represented functionally. just bindings. The recent paper [14] introduces a syntactic framework that 7.2 Systems with one arrow type constructor treats bindings as primitives. That framework is then integrated with various tools and with the framework of contextual types The Delphin design is probably the closest to MLTS, in particu- (similar to that found in Beluga) in order to provide a program- lar [56] introduced a programming-language version of the ∇ quan- mer of, say, OCaml with sophisticated tools for the manipulation tifier from [39], whose usage is related to the ∇ of MLTS. In Del- of syntax and binders. A possible future target for MLTS could be phin, ∇ introduces normal term variables (there is no separate class to provide such tools more directly in the language itself. of nominal constants), while MLTS presents nominals as closer to datatype constructors, with a natural usage in pattern-matching. 7.4 Challenge problems and benchmarks Delphin makes nominal-escape errors impossible at runtime by imposing a static discipline to prevent them, while MLTS allows Genuine comparisons between different programming languages runtime failure in order to allow for more experimentation. The are generally hard to achieve. For example, in the area of logical original proposal in [56] uses a type modality that imposes a strict frameworks and related theorem provers, there are also a number FIFO discipline on free variables. This discipline was found too of formal systems and implementations. In order to un- constraining; [50] completely eschews a new construct (its νx. e derstand the relative merits of these different systems, challenge binder actually corresponds to nominal abstraction X\e in MLTS), problems and benchmarks [2, 13] have been proposed to help peo- and [51] uses a type-based restriction (type subordination), only ple sort out specific merits and challenges of one system relative to allowing to introduce a fresh nominal in expressions whose return another. In depth comparisons of the programming languages de- types only contains values that cannot contain this nominal. This scribed above will probably require similar in-depth comparisons discipline accepts some examples from our paper, for example size on representative programming tasks. in Figure 1 and id in Figure 4, but rejects other (safe) programs, such as the second and third one-liner examples of Section 2.3. 8 CONCLUSION Richer static disciplines have been proposed for FreshML [49, 53], While the λ-tree syntax approach to computing with syntax con- but they add complexity, and interact poorly with the introduction taining bindings has been successfully developed within the logic of mutable state; MLTS is an experimental design aiming for ex- programming setting (in particular, in λProlog and Twelf), we pro- pressivity, so we decided to allow dynamic escape failures instead. vide in this paper another example of how binding can be captured Beluga [47] allows the programmer to use both dependent types in a functional programming language. Most of the expressiveness and recursive definitions as well as an integrated notion of context of MLTS arises from its increased use of program-level binding. (along with a method to describe certain invariants using context The sophistication needed to correctly exploit binders and quanti- schema). Static checks of Beluga programs can be used to prove fiers in MLTS is a skill most people have learned from using quan- the formal correctness of Beluga programs (commonly by proving tification in, for example, predicate logic. that a given piece of program code is, in fact, a total function). As We have presented a number of MLTS programs and we note a result, a checked Beluga program is often a formal proof. Since that they are both natural and unencumbered by concerns about a wide range of formal systems can be encoded naturally using de- managing bound variable names. We have also presented a typing pendently typed λ-terms [1, 24], Beluga programs can be used for discipline for MLTS as well as a formal specification of its natural both programming with and reasoning about the meta-theory of semantics: this latter task was aided by being able to directly ex- those formal systems. Since bindings and contexts are part of the ploit a rich logic, called G, that allows capturing both λ-tree syn- vocabulary of Beluga, these formal proofs can capture the metathe- tax and binder mobility. Finally, the natural semantics specification ory of logical and computational systems (such as natural deduc- and the typing system were directly implementable in λProlog. A tion proof systems and the operational semantics of rich program- prototype implementation is available for helping to judge the ex- ming languages). The goal of MLTS is intended only to support pressiveness of MLTS programs. Functional programming with λ-tree syntax PPDP ’19, October 7–9, 2019, Porto, Portugal

Acknowledgments. We thank Kaustuv Chaudhuri, François Pot- REFERENCES tier, Enrico Tassi, the HOPE Workshop 2018 audience, and the anony- [1] Arnon Avron, Furio Honsell, Ian A. Mason, and Robert Pollack. 1992. Using mous reviewers for their helpful comments and observations. Typed to Implement Formal Systems on a Machine. Journal of Automated Reasoning 9 (1992), 309–354. https://doi.org/10.1007/BF00245294 [2] Brian E. Aydemir, Aaron Bohannon, Matthew Fairbairn, J. Nathan Fos- ter, Benjamin C. Pierce, Peter Sewell, Dimitrios Vytiniotis, Geoffrey Wash- burn, Stephanie Weirich, and Steve Zdancewic. 2005. Mechanized Metathe- ory for the Masses: The POPLmark Challenge. In Theorem Proving in Higher Order Logics: 18th International Conference (LNCS). Springer, 50–65. https://doi.org/10.1007/11541868_4 [3] David Baelde, Kaustuv Chaudhuri, Andrew Gacek, Dale Miller, Gopalan Na- dathur, Alwen Tiu, and Yuting Wang. 2014. Abella: A System for Reasoning about Relational Specifications. Journal of Formalized Reasoning 7, 2 (2014), 1– 89. https://doi.org/10.6092/issn.1972-5787/4650 [4] Arthur Charguéraud. 2011. The Locally Nameless Representation. Journal of Au- tomated Reasoning (May 2011), 1–46. https://doi.org/10.1007/s10817-011-9225-2 [5] James Cheney and Christian Urban. 2004. Alpha-Prolog: A Logic Programming Language with Names, Binding, and Alpha-Equivalence. In Logic Programming, 20th International Conference (LNCS), Bart Demoen and Vladimir Lifschitz (Eds.), Vol. 3132. Springer, 269–283. https://doi.org/10.1007/978-3-540-27775-0_19 [6] Anthony S. K. Cheng, Peter J. Robinson, and John Staples. 1991. Higher Level Meta Programming in Qu-Prolog 3: 0. In Logic Programming, Proceedings of the Eigth International Conference, Paris, France, June 24-28, 1991, Koichi Furukawa (Ed.). MIT Press, 285–298. [7] Jawahar Chirimar. 1995. Proof Theoretic Approach to Specifica- tion Languages. Ph.D. Dissertation. University of Pennsylvania. http://www.lix.polytechnique.fr/Labo/Dale.Miller/chirimar/phd.ps [8] Adam Chlipala. 2008. Parametric higher-order abstract syntax for mecha- nized semantics. In Proceeding of the 13th ACM SIGPLAN international con- ference on Functional programming, ICFP 2008, Victoria, BC, Canada, Sep- tember 20-28, 2008, James Hook and Peter Thiemann (Eds.). ACM, 143–156. https://doi.org/10.1145/1411204.1411226 [9] . 1940. A Formulation of the Simple Theory of Types. J. of Sym- bolic Logic 5 (1940), 56–68. https://doi.org/10.2307/2266170 [10] Nicolaas Govert de Bruijn. 1972. Lambda Calculus Notation with Nameless Dummies, a Tool for Automatic Formula Manipulation, with an Application to the Church-Rosser Theorem. Indagationes Mathematicae 34, 5 (1972), 381–392. https://doi.org/10.1016/1385-7258(72)90034-0 [11] Joëlle Despeyroux, Amy Felty, and Andre Hirschowitz. 1995. Higher-order ab- stract syntax in . In Second International Conference on Typed Lambda Calculi and Applications. 124–138. https://doi.org/10.1007/BFb0014049 [12] Cvetan Dunchev, Ferruccio Guidi, Claudio Sacerdoti Coen, and Enrico Tassi. 2015. ELPI: Fast, Embeddable, λProlog Interpreter. In Logic for Programming, Artificial Intelligence, and Reasoning - 20th International Conference, LPAR-20 2015, Suva, Fiji, November 24-28, 2015, Proceedings (LNCS), Martin Davis, Ans- gar Fehnker, Annabelle McIver, and Andrei Voronkov (Eds.), Vol. 9450. Springer, 460–468. https://doi.org/10.1007/978-3-662-48899-7_32 [13] Amy P. Felty, Alberto Momigliano, and Brigitte Pientka. 2015. The Next 700 Challenge Problems for Reasoning with Higher-Order Abstract Syntax Repre- sentations: Part 2–A Survey. J. of Automated Reasoning 55, 4 (2015), 307–372. https://doi.org/10.1007/s10817-015-9327-3 [14] Francisco Ferreira and Brigitte Pientka. 2017. Programs Using Syntax with First- Class Binders. In Proceedings of the 26th European Symposium on Programming, ESOP 2017, Uppsala, Sweden (Lecture Notes in ), Hongseok Yang (Ed.), Vol. 10201. Springer, 504–529. [15] M. J. Gabbay and A. M. Pitts. 1999. A new approach to abstract syntax involving binders. In 14th Symp. on Logic in Computer Science. IEEE Computer Society Press, 214–224. [16] Andrew Gacek. 2009. A Framework for Specifying, Prototyping, and Reasoning about Computational Systems. Ph.D. Dissertation. University of Minnesota. [17] Andrew Gacek, Dale Miller, and Gopalan Nadathur. 2008. Combining generic judgments with recursive definitions. In 23th Symp. on Logic in Computer Science, F. Pfenning (Ed.). IEEE Computer Society Press, 33–44. https://doi.org/10.1109/LICS.2008.33 [18] Andrew Gacek, Dale Miller, and Gopalan Nadathur. 2011. Nomi- nal abstraction. Information and Computation 209, 1 (2011), 48–73. https://doi.org/10.1016/j.ic.2010.09.004 [19] Ulysse Gérard. 2019. Computing with relations, functions, and bindings. Ph.D. Dissertation. University of Paris Saclay. http://www.lix.polytechnique.fr/Labo/Dale.Miller/gerard19phd. [20] Ulysse Gérard, Dale Miller, and Gabriel Scherer. 2018. Try MLTS Online. https://trymlts.github.io/. [21] A. Gordon. 1994. A Mechanisation of Name-Carrying Syntax up to Alpha- Conversion. In International Workshop on Higher Order Logic Theorem Proving and its Applications (Lecture Notes in Computer Science), Vol. 780. 414–426. [22] Michael J. Gordon, Arthur J. Milner, and Christopher P. Wadsworth. 1979. Edin- burgh LCF: A Mechanised Logic of Computation. LNCS, Vol. 78. Springer. PPDP ’19, October 7–9, 2019, Porto, Portugal Ulysse Gérard, Dale Miller, and Gabriel Scherer

[23] Michael J. C. Gordon. 1991. Introduction to the HOL System. In Proceedings of the Symposium on Programming (ESOP 2008). International Workshop on the HOL Theorem Proving System and its Applications, [51] Adam Poswolsky and Carsten Schürmann. 2008. System Description: Delphin Myla Archer, Jeffrey J. Joyce, Karl N. Levitt, and Phillip J. Windley (Eds.). IEEE - A Functional Programming Language for Deductive Systems, In International Computer Society, 2–3. Workshop on Logical Frameworks and Meta-Languages: Theory and Practice [24] Robert Harper, Furio Honsell, and Gordon Plotkin. 1993. A Frameworkfor Defin- (LFMTP 2008), A. Abel and C. Urban (Eds.). Electr. Notes Theor. Comput. Sci. 228, ing Logics. J. ACM 40, 1 (1993), 143–184. 113–120. [25] John Harrison. 2009. HOL Light: an overview. In International Conference on [52] François Pottier. 2006. An Overview of Cα ml. In Proceedings of the ACM- Theorem Proving in Higher Order Logics. Springer, 60–66. SIGPLAN Workshop on ML (ML 2005) (Electr. Notes Theor. Comput. Sci.), Vol. 148. [26] Gérard Huet. 1975. A Unification for Typed λ-Calculus. Theoretical 27–52. https://doi.org/10.1016/j.entcs.2005.11.039 Computer Science 1 (1975), 27–57. https://doi.org/10.1016/0304-3975(75)90011-0 [53] François Pottier. 2007. Static name control for FreshML. In 22nd Annual IEEE [27] js-of- 2018. Js_of_ocaml. http://ocsigen.org/js_of_ocaml/. Symposium on Logic in Computer Science (LICS 2007). IEEE, 356–365. [28] Gilles Kahn. 1987. Natural Semantics. In Proceedings of the Symposium on Theo- [54] Xiaochu Qi, Andrew Gacek, Steven Holte, Gopalan Nadathur, and Zach retical Aspects of Computer Science (LNCS), Franz-Josef Brandenburg, Guy Vidal- Snow. 2015. The Teyjus System – Version 2. http://teyjus.cs.umn.edu/ Naquet, and Martin Wirsing (Eds.), Vol. 247. Springer, 22–39. http://teyjus.cs.umn.edu/. [29] Daniel R. Licata and Robert Harper. 2009. A Universe of Binding and Com- [55] Davide Sangiorgi. 1996. π -calculus, internal mobility and agent-passing calculi. putation. In Proceedings of the 14th ACM SIGPLAN International Conference Theoretical Computer Science 167, 2 (1996), 235–274. on Functional Programming (ICFP ’09). ACM, New York, NY, USA, 123–134. [56] Carsten Schürmann, Adam Poswolsky, and Jeffrey Sarnat. 2005. The nabla- https://doi.org/10.1145/1596550.1596571 calculus. Functional Programming with Higher-order Encodings. In Proceedings [30] Conor McBride and James McKinna. 2004. Functional pearl: I am not a num- of the 7th International Conference on Typed Lambda Calculi and Applications ber - I am a free variable. In Proceedings of the ACM SIGPLAN Workshop on (TLCA’05). https://doi.org/10.1007/11417170_25 Haskell, Haskell 2004, Snowbird, UT, USA, September 22-22, 2004, Henrik Nilsson [57] Helmut Schwichtenberg. 2006. Minlog. In The Seventeen Provers of (Ed.). ACM, 1–9. http://doi.acm.org/10.1145/1017472.1017477 the World (LNCS), Freek Wiedijk (Ed.), Vol. 3600. Springer, 151–157. [31] Dale Miller. 1990. An Extension to ML to Handle Bound Vari- https://doi.org/10.1007/11542384_19 ables in Data Structures: Preliminary Report. In Proceedings of [58] Dana Scott. 1970. Outline of a Mathematical . In Proceed- the Logical Frameworks BRA Workshop. Antibes, France, 323–335. ings, Fourth Annual Princeton Conference on Information Sciences and Systems. http://www.lix.polytechnique.fr/Labo/Dale.Miller/papers/mll.pdf Available as Princeton University, 169–176. Also, Programming Research Group Technical UPenn CIS technical report MS-CIS-90-59. Monograph PRG–2, Oxford University. [32] Dale Miller. 1991. A Logic Programming Language with Lambda-Abstraction, [59] M. R. Shinwell, A. M. Pitts, and M. J. Gabbay. 2003. FreshML: Programming Function Variables, and Simple Unification. J. of Logic and Computation 1, 4 with Binders Made Simple. In Eighth ACM SIGPLAN International Conference on (1991), 497–536. https://doi.org/10.1093/logcom/1.4.497 Functional Programming (ICFP 2003), Uppsala, Sweden. ACM Press, 263–274. [33] Dale Miller. 1992. Unification under a mixed prefix. Journal of Symbolic Compu- [60] Yuting Wang, Kaustuv Chaudhuri, Andrew Gacek, and Gopalan Nadathur. tation 14, 4 (1992), 321–358. https://doi.org/10.1016/0747-7171(92)90011-R 2013. Reasoning about Higher-Order Relational Specifications. In Proceed- [34] Dale Miller. 1996. Forum: A Multiple-Conclusion Specification ings of the 15th International Symposium on Princples and Practice of Declar- Logic. Theoretical Computer Science 165, 1 (Sept. 1996), 201–232. ative Programming (PPDP), Tom Schrijvers (Ed.). Madrid, Spain, 157–168. https://doi.org/10.1016/0304-3975(96)00045-X https://doi.org/10.1145/2505879.2505889 [35] Dale Miller. 2004. Bindings, mobility of bindings, and the ∇-quantifier. In 18th International Conference on Computer Science Logic (CSL) 2004 (LNCS), Jerzy Marcinkowski and Andrzej Tarlecki (Eds.), Vol. 3210. 24. https://doi.org/10.1007/978-3-540-30124-0_4 [36] Dale Miller. 2018. Mechanized Metatheory Revisited. Journal of Automated Reasoning (04 Oct. 2018). https://doi.org/10.1007/s10817-018-9483-3 [37] Dale Miller and Gopalan Nadathur. 2012. Programming with Higher-Order Logic. Cambridge University Press. https://doi.org/10.1017/CBO9781139021326 [38] Dale Miller and Catuscia Palamidessi. 1999. Foundational Aspects of Syntax. Comput. Surveys 31 (Sept. 1999). [39] Dale Miller and Alwen Tiu. 2005. A proof theory for generic judg- ments. ACM Trans. on Computational Logic 6, 4 (Oct. 2005), 749–783. https://doi.org/10.1145/1094622.1094628 [40] Gopalan Nadathur and Dale Miller. 1988. An Overview of λProlog. In Fifth International Logic Programming Conference. MIT Press, Seattle, 810–827. http://www.lix.polytechnique.fr/Labo/Dale.Miller/papers/iclp88.pdf [41] Tobias Nipkow. 1993. Functional Unification of Higher-Order Patterns. In 8th Symp. on Logic in Computer Science, M. Vardi (Ed.). IEEE, 64–74. [42] OCaml. 2018. http://ocaml.org/. [43] Lawrence C. Paulson. 1989. The Foundation of a Generic Theorem Prover. Jour- nal of Automated Reasoning 5 (Sept. 1989), 363–397. [44] Lawrence C. Paulson. 1994. Isabelle: A Generic Theorem Prover. Number 828 in LNCS. Springer Verlag. [45] Frank Pfenning and Conal Elliott. 1988. Higher-Order Abstract Syntax. In Pro- ceedings of the ACM-SIGPLAN Conference on Programming Language Design and Implementation. ACM Press, 199–208. [46] Frank Pfenning and Carsten Schürmann. 1999. System Description: Twelf — A Meta-Logical Framework for Deductive Systems. In 16th Conf. on Auto- mated Deduction (CADE) (LNAI), H. Ganzinger (Ed.). Springer, Trento, 202–206. https://doi.org/10.1007/3-540-48660-7_14 [47] Brigitte Pientka and Joshua Dunfield. 2010. Beluga: A Framework for Program- ming and Reasoning with DeductiveSystems (System Description). In Fifth Inter- national Joint Conference on Automated Reasoning (LNCS), J. Giesl and R. Hähnle (Eds.). 15–21. [48] Andrew M. Pitts. 2003. Nominal Logic, A First Order Theory of Names and Binding. Information and Computation 186, 2 (2003), 165–193. [49] A. M. Pitts and M. J. Gabbay. 2000. A Metalanguage for Programming with Bound Names Modulo Renaming. In Mathematics of Program Construction. 5th International Conference, MPC2000, Ponte de Lima, Portugal, July 2000. Proceed- ings (LNCS), R. Backhouse and J. N. Oliveira (Eds.), Vol. 1837. Springer, Heidel- berg, 230–255. [50] Adam Poswolsky and Carsten Schürmann. 2008. Practical programming with higher-order encodings and dependent types. In Proceedings of the European