Formalisation in Constructive Type Theory of Barendregt's Variable Convention for Generic Structures with Binders

07/05/2018 ∙ by Ernesto Copello, et al. ∙ The University of Iowa Universidad ORT Uruguay 0

We introduce a universe of regular datatypes with variable binding information, for which we define generic formation and elimination (i.e. induction /recursion) operators. We then define a generic alpha-equivalence relation over the types of the universe based on name-swapping, and derive iteration and induction principles which work modulo alpha-conversion capturing Barendregt's Variable Convention. We instantiate the resulting framework so as to obtain the Lambda Calculus and System F, for which we derive substitution operations and substitution lemmas for alpha-conversion and substitution composition. The whole work is carried out in Constructive Type Theory and machine-checked by the system Agda.

READ FULL TEXT VIEW PDF
POST COMMENT

Comments

There are no comments yet.

Authors

page 1

page 2

page 3

page 4

This week in AI

Get the week's most popular data science and artificial intelligence research sent straight to your inbox every Saturday.

1 Introduction

The definition of functions by recursion on the description of datatypes is the basic idea of generic programming. This method is based on defining a datatype, introduced as the universe [13], which contains datatype descriptions, such as “a list is either empty or a pair consisting of a parameter and a sublist”. Indeed, the universe constructors correspond to the common notions “either”, “pair”, “parameter” and “substructure” abstracted out of informal descriptions such as the preceding one. Then a decoding function is introduced, which interprets instances of the universe, usually called universe codes, into actual datatypes. In a dependently typed setting we can define generic functions over the universe of codes and the associated decoded datatypes. In other words, the codes provide information enough to properly traverse the structure of decoded datatype instances. Thereby, traversal becomes an operation that can be described for any recursive structure by means of generic iteration and recursion principles and, thus, code duplication is avoided by abstracting out basic operations on the datatypes. One can wonder how many other practical behaviors can undergo such kind of generalisation.

In this work we introduce a universe of regular trees [14] extended with variables (i.e. names) and binding information. We first define generic formation and elimination (i.e. induction/recursion) operators over this universe. The inclusion of names and the notion of locality allow us to introduce a generic -equivalence relation, which we choose to base on name-swapping. Then we derive -iteration and induction principles that capture Barendregt’s Variable Convention (BVC) which allows to proceed in proofs and definitions by conveniently choosing bound names so as to avoid conflict. At this generic level we are able to prove several properties, mainly concerning the interaction of the iteration and recursion principles with the swapping operation and -equivalence relation. We next obtain -calculus and System F as instances of our universe and define corresponding substitution operations as instances of the generic -iteration principle. We are thereby able to derive the lemmas on compatibility of substitution with -equivalence by direct instantiation of the generic properties referred to above. Finally, we prove the substitution composition lemma for the System F showing how our approach allows us to mimic the BVC, proving particular results on instances of the framework as it is usually done in pen-and-paper style.

1.1 Related work

Programming languages supporting native constructions to declare and manipulate abstract syntax with binders are presented by Shinwell, et. al in [18, 17], where an ML extension FreshML, and an OCaml extension Fresh O’Caml are respectively developed. These languages allow to deconstruct datatypes with binders in a safe way, that is, in the case of an abstraction inspection, a renaming with a freshly generated binder is computed for the abstraction body. In this way, the language user has access only to a fresh binder, and the renamed body of the opened abstraction. This mechanism grants that values with binders are operationally equivalent if they represent -equivalent objects. This result is proved in [18] by introducing a denotational semantics of the object language FreshML into FM-sets (Fraenkel and Mostowski’s sets). They prove that this denotational semantics matches the operational one. In this way, they are able to prove that values of the introduced abstract syntax with binders properly represent -equivalence classes of the object-level syntax. In [6] Cheney carries out a similar work, but instead of developing a language extension, he implements a Haskell library called FreshLib. As the author does not implement a language from scratch, this work introduces generic programming techniques in its implementation to support the required level of genericity.

All previous works address common operations dealing with general structures with binders. Although some of these developments give proofs about the soundness of their approaches, their main concern is the implementation of meta-programs. In [11], Lee et al. use generic programming techniques to develop mechanisations of formal meta-theory in the Coq proof assistant. This work allows the user to choose between nominal, locally nameless or de Bruijn first-order syntax. For each of these representations, they offer several infrastructure operations and their associated lemmas. For instance, for the locally nameless setting, two different substitutions are needed for bound and free variables respectively. In the case of System F, where terms and type variables have binding constructions, this representation involves six different substitution operations. Hence, as the number of syntactic sorts supporting binding constructions increases in the object language, there is a combinatorial explosion of the number of operations and lemmas involved in its formalisation for the locally nameless and de Bruijn first-order syntaxes. They manage to address these issues defining these operations and associated lemmas in a generic re-usable way. Moreover, they provide a small annotation language to describe the binding structure of the object language, from which they can automatically derive an isomorphism between the object language and their generic universe syntax. However, introducing inductive relations in this framework requires the user to provide a mapping between the concrete relation, defined at the object language level, and the generic relation. They are able to instantiate some cases of the POPLmark challenge [3] in their framework, validating their approach both for the locally nameless and the de Bruijn first-order syntax, and comparing some metrics of their approach against other solutions. However, their particular choice of universe makes it impossible to have more than one sort of binder per datatype. Hence, they cannot represent in their setting a language such as Session Types [20], where there exist three distinct sort of binders: parameters, channels and ports within a concurrent calculus. We believe their work addresses reusing and usability in great manner, but lacks in extensibility and abstraction. By using this framework it is possible to reuse several operations and lemmas that hide some of the work required by the underlying binders representation. However, in order to introduce new operations and prove results, the user may have to deal with the underlying generic abstract syntax language. Their work seems to support the nominal syntax, although no -conversion relation, neither any other classic relation, property or function over named terms is presented. Indeed, they do not further develop the nominal syntax, beyond the basic definitions of a nominal abstract syntax.

In [12], Licata and Harper codify a universe that mixes binding and computation constructions in Agda, where computations are represented as meta-level functions injected in the universe constructions, i.e., they embed a HOL syntax in their development. Their representation is based on a well-scoped de Bruijn representation, that is, de Bruijn terms associated with a context indexing the free variables. For this universe, they provide a generic substitution operation, and prove context weakening and strengthening lemmas. In 2002 Pitts and Gabbay introduced the Nominal Logic [10], a first-order many-sorted logic with equality, containing primitives for renaming via name-swapping, for freshness of names, and for name-binding. The swapping operation has much nicer logical properties than the more general, non-bijective forms of renaming. This operation provides a sufficient foundation for a theory of structural induction/recursion for the syntax modulo . In [19], Urban and Tasson use ideas from Nominal Logic to construct a set of -calculus terms modulo alpha, that is, identifying -convertible terms. The construction is based on a HOAS syntax on top of Isabelle/HOL, deriving recursion and induction principles over this quotient set.

Our main motivation is to show it is feasible to formalise within constructive type theory -iteration/ induction principles for a classical named syntax, deriving these principles from just simple structural induction on fist-order terms, where equality remains the simple definitional one, and not performing any kind of quotient on terms. Then, we want to study how feasible is to use this development in practical examples. This work is structured as follows: in Section 2 we present our regular tree universe, in Section 3 we introduce name-swapping, in Section 4 we give an -conversion relation and iteration/induction schemes modulo , which allow us to define the caputre-avoiding subtitution operation, and automatically derive some of its basic properties. In Section 5 we introduce the proof technique that mimics the BVC, and we apply it in the substitution composition lemma. Finally, in the last section we discuss related work and conclusions. We carry out the whole development within Constructive Type Theory as implemented in the system Agda [15]. We will show fragments of the Agda code, the complete version being available at: https://github.com/ernius/genericBindingFramework.

2 Universe of Regular Trees with Binders

2.1 Universe of (Codes of) Functors

We choose to build up a universe whose objects are codes to be interpreted as functions from Set to Set111Set is the type of (small) datatypes., i.e. as functors. The actual datatypes generated by this mechanism arise as fixed points of such functors. To this effect, we introduce in Figure 1:

  • the datatype Functor of codes, and

  • the (mutually recursive-inductive) definition of the decoding function ⟦_⟧ and of the actual datatype μ  associated to any given functor code .

Functor [GenericProgramming/GPBindings.tex]functor [GenericProgramming/GPBindings.tex]interpret μ [GenericProgramming/GPBindings.tex]mu

Figure 1: Regular tree universe with binders.

Notice first that the (inductive) definition of μ  by means of the constructor indeed introduces it as the least fixed point of the functor corresponding to the code . Now let us examine the codes and corresponding functors. The first three constructors of datatype Functor in Figure 1 represent the embedding of: the unity type, a recursive position, and an arbitrary (i.e. externally given) datatype. The fourth constructor embeds a datatype representable in our universe, while the next two constructors represent the sum and product of types. Finally, the last two introduction rules are specific to our desired domain of abstract syntaxes with binders. As our framework supports different sorts of names, the variables and binders constructors receive as parameters an identifier of the sort of variables that they respectively introduce or bind. The binder constructor also receives the descriptor of the structure serving as scope of the bound variable. In many cases of interest (e.g. the -calculus and System F to be examined shortly) this subterm descriptor will be just a recursive position. However, a compound structure is often needed, as it is the case in e.g. languages with a letrec primitive. We can observe how the variable and binder constructions inject a fixed set of variables (names)  into the interpreted datatype. This set  is assumed to be infinite with a decidable equality. Notice too that in the cases of the variable injection and the binder functors the sort argument  has no impact on the interpreted set. Indeed, we have only one kind of names . The sort identifier will be relevant to implement generic operations related to binding issues, as shown in subsequent sections.

For example, the types of natural numbers and of lists of natural numbers can be defined as follows:

In Figure 2 we illustrate the use of the variables and binders constructions by encoding the -calculus. We show the corresponding classical concrete syntax definition using comments, that are written following a dash to the right of each line. This definition has only one sort of variables identified with the sort SortλTermVars.

[GenericProgramming/Examples/LambdaCalculus.tex]lambdacalculus [GenericProgramming/Examples/LambdaCalculus.tex]lambdacalculusmu
Figure 2: -calculus.

We next introduce notation resembling the concrete syntax of the -calculus and hiding away our universe code constructions.

[GenericProgramming/Examples/LambdaCalculus.tex]lambdaconstvar

[GenericProgramming/Examples/LambdaCalculus.tex]lambdaconstapp

[GenericProgramming/Examples/LambdaCalculus.tex]lambdaconstlam

Next we present the codification of the System F. As this language also needs bindings at the type level, this encoding illustrates the use of two distinct sorts of identifiers, namely SortFTypeVars and SortλTermVars:

[GenericProgramming/Examples/SystemF.tex]systemF

[GenericProgramming/Examples/SystemF.tex]systemFmuty

[GenericProgramming/Examples/SystemF.tex]systemFmutrm

In the preceding constructions we have chosen a simplification of the universe of regular tree datatypes presented in [14], where recursive types are represented using -types (from [16]). However, instead of the nominal approach traditionally used with recursive type binders, they use a well-scoped de Bruijn representation. Therefore, in order to properly interpret the full universe, a definition indexed by a context with the multiple -recursive positions definitions is required. Our representation in Agda (Figure 1), simplifies this burden at the expense of not being able to represent mutually recursive datatypes. In other words, our universe construction has expressive power equivalent to admitting only a single top-level -recursive type binder.

2.2 Map and Fold

The classical definition of fold based on map that is usually introduced in category theory does not pass Agda’s termination checker. The recursive call to fold is hidden inside a call to map, and because of this the termination checker cannot determine how map is using it. To make the fold operation pass the termination checker we have to fuse map and fold into a single function, as done in [15] for a similar regular tree universe. In Figure 3 we show our implementation of the function foldmap. We make use of Agda’s implicit arguments feature, denoted by curly braces, to omit terms that the type checker can figure out for itself. For instance, we declare the set argument as an implicit argument. The presented foldmap function needs to keep two functors, since the fold (recursive) part works always over the same functor argument , while, for the map part, the auxiliary functor argument  gives the position of functor during the traversal of the structure. Therefore, this function only uses the functor  in the recursive case rule (the |R| case) in which the right hand side expression basically begins a new traversal of the functor , in a way similar to the original definition of fold. It does so by providing with a fresh copy of  in the position of the auxiliary argument . The rest of the rules are equivalent to a map over the functor . Note that this definition terminates because the argument of type ⟦ G ⟧ (μ F) decreases in each recursive call. The new fold operation is defined as a recursive instance of foldmap.

[GenericProgramming/GPBindings.tex]foldmap
[GenericProgramming/GPBindings.tex]foldmap2

Figure 3: Terminating fold operation.

As an example, we define a function vars that counts the number of variable occurrences in a term of the -calculus. We do so by instantiating it as a case of the fold operation in fig. 4

[GenericProgramming/Examples/LambdaCalculus.tex]varsfold1 [GenericProgramming/Examples/LambdaCalculus.tex]varsfold2
Figure 4: Fold application example.

Next we present a particular useful instantiation of the fold operator, named foldCtx. This instantiation aims at reproducing some techniques related to the nominal syntax considered in our work. We introduce an extra argument with type μ C, which is used by the folded function . This function is partially applied to this extra argument, and then passed as an argument of fold. Hence, this argument acts as an explicit invariant context for the function  through the entire fold operation. Another difference with the original fold operation is that the result of this instance is a datatype μ H encoded in our universe instead of an arbitrary set.

[GenericProgramming/GPBindings.tex]foldCtx

From this fold instance we can directly derive the naive substitution operation for the -calculus. In order to do this, we next give the functor descriptor cF for the context argument. It represents the pair formed by the variable to be replaced and the substituted term:

[GenericProgramming/Examples/LambdaCalculus.tex]substcontext

Next we define the function substaux (Figure 5) to be folded which, given a term structure with the results of the recursive calls in its recursive positions, constructs the final result of the substitution. For the variable case, we check, as usual, whether the substitution is to be applied, whereas the application and abstraction cases directly reconstruct the corresponding terms from the recursive call. Note that in the abstraction case we do not check whether the abstracted variable is different from the one being replaced, as in Barendregt’s substitution definition in [4]. In fact, this comparison would be pointless because, as we are using an iteration principle, we do not have access to the original abstraction body subterm. Note that we hide the universe codes on the right side of this definition by using the previously introduced -calculus constructors.

[GenericProgramming/Examples/LambdaCalculus.tex]substaux

Figure 5: Naive substitution auxiliary function.

Finally, we instantiate the foldCtx function with substaux, and its appropriate context pair to get the naive substitution operation.

[GenericProgramming/Examples/LambdaCalculus.tex]naivesubst

2.3 Primitive Induction

We now develop a more generic elimination rule than the fold operation defined above. This elimination rule captures proof by induction, and is based on the recursion rule given by Benke et al. in [5]. However, our development departs from their work in the following points: Firstly, they derive an elimination rule for a simpler universe construction, based on one-sorted term algebras, and defined through signatures instead of functors. For instance, their universe does not allow the injection of previously defined datatypes, which is necessary for defining e.g. lists of natural numbers so as natural numbers become parts of the lists. Secondly, their induction principle would not pass Agda’s termination checker due to reasons similar to the ones discussed for the first version of the fold operation. To define the desired function, to be called foldInd, we first introduce the auxiliary function fih (Figure 6).

[GenericProgramming/GPBindings.tex]primIndih

Figure 6: fih function.

This function receives a predicate  over the fixed point of a functor , and an auxiliary functor (with a similar functionality to the one used in the foldmap function). It returns a corresponding predicate of type ⟦ G ⟧ (μ F) → Set. This resulting predicate represents  holding for every recursive position μ F in an element of type ⟦ G ⟧ (μ F).

We can now present our induction principle. We proceed in a similar way as we did above for the fold function. First, we introduce the fold-map fusion function foldmapFh (Figure 7). Then, we use this function to directly derive the induction principle as a recursive instance of the fold-map fusion.

[GenericProgramming/GPBindings.tex]primInd
[GenericProgramming/GPBindings.tex]primInd2

Figure 7: Induction principle.

We next give an example of the use of this induction principle, namely proving that the application of the function vars to any lambda term is greater than zero. We introduce the predicate Pvars representing the property to be proved and an auxiliary lemma plus>0, stating that the sum of two positive numbers is also positive.

[GenericProgramming/Examples/LambdaCalculus.tex]varsproof1

[GenericProgramming/Examples/LambdaCalculus.tex]varsproof2

The proof that Pvars holds for every term M is a direct application of the induction principle. The variable case is direct, while the application case is the application of the lemma plus>0 to the induction hypotheses. Finally, the abstraction case is a direct application of the induction hypothesis.

[GenericProgramming/Examples/LambdaCalculus.tex]proofpvars

[GenericProgramming/Examples/LambdaCalculus.tex]proof

3 Name-Swapping

We now turn to considering a very basic primitive of name-swapping, which will be used for defining -conversion without a mention to substitution. This constitutes the foundation of the implementation of the general idea that principles of recursion and induction ought to be defined so as to work modulo -conversion, thus allowing to mimic the usual pen-an-paper conventions that allow the choice of convenient representatives of the terms involved in a definition or proof. The name-swapping operation completely traverses a data structure, swapping occurrences (either free, bound or binding) of two given names of some sort. Its implementation (Figure 8) is similar to that of fold.

[GenericProgramming/Swap.tex]swapF
[GenericProgramming/Swap.tex]swap

Figure 8: Name-swapping operation.

We use an auxiliary function swapF, that takes functors and , and traverses the structure until a recursive or embedded position is reached, from where we restart the argument with either the original recursive functor  or the embedded functor respectively. Note that this treatment differs from the one in the definition of fold, where this case is a base case. Here we must also traverse the embedded functor instance, as we are swapping all the variables in the structure, including the variables present in any embedded structure. Because of this, we cannot derive name-swapping as an instance of fold. In the variable and abstraction cases we use name-swapping over variables 222Requiring the decidable equality over names., denoted by the (mixfix) operator (∙)ₐ  as in [8].

We prove a generic lemma about the interaction between name-swapping and the iteration principle. This lemma is presented in Figure 9, and states that the fold instance with context information is well-behaved with respect to name-swapping, given that the respectively folded operation is also well-behaved. Its proof goes by a direct induction on terms. This example shows how we are able to develop generic proofs over our universe with binders.

[GenericProgramming/Swap.tex]swapfoldCtx

Figure 9: Fold with context is well-behaved with respect to name-swapping.

We are able to directly apply the preceding lemma to the -calculus case in order to prove the result in Figure 10. This states that name-swapping commutes with substitution, which is particularly useful. We introduce the operator (∙)  to denote the swapping of variables in terms. In the proof we use of the auxiliary lemma lemma-substauxSwap which states that the function substaux, used to define substitution, is well-behaved with respect to name-swapping. This example shows how feasible it is in our framework to instantiate generic proofs for deriving useful lemmas holding for particular instances of the generic universe.

[GenericProgramming/Examples/LambdaCalculus.tex]swapsubst

Figure 10: Substitution is well-behaved with respect to name-swapping.

In a similar manner we introduce a generic function returning the free variables of terms, and prove several properties about its interaction with swapping, fold, and -conversion.

4 Alpha Equivalence Relation.

[GenericProgramming/Alpha.tex]alpha

Figure 11: Alpha equivalence relation.

In Figure 11 we introduce the generic definition of the -equivalence relation over our universe, named ∼α. Its definition follows a process similar to the one used before to implement generic functions over our universe. First, we define an auxiliary relation ∼αF, which is inductively defined introducing an auxiliary functor , used to traverse the functor  structure. For the interesting binder case, we follow an idea similar to the one used in [8], that is, we define that two abstractions are -equivalent if there exists some list of variables , such that for any given variable  not in , the result of swapping the corresponding binders with  in the abstraction bodies is -equivalent. Note that the swapping is performed only over the sort of variables bound by this binder position, leaving any other sort of variables unchanged. We are able to prove that this is an equivalence relation, and also that it is preserved under name-swapping in a similar way as done in our previous work [8].

As we did before with name-swapping, we study how the iteration principle interacts with the introduced -equivalence relation. We begin proving that the fold operation is -compatible if it is applied to an also -compatible function. We say a function is -compatible iff it returns -convertible results when it is applied to -convertible arguments. In Figure 12 we state this lemma, whose proof goes by induction on terms. The only interesting case is the binders case, where we make use of the preservation of -equivalence under name-swapping.

[GenericProgramming/Alpha.tex]lemma-foldfalpha

Figure 12: Fold function -compatibility property.

As a direct corollary we get that the fold with context instance is -compatible in its context argument provided the folded function is also -compatible on its arguments (Figure 13).

[GenericProgramming/Alpha.tex]lemmafoldCtxalphactx

Figure 13: Fold context function -compatibility corollary.

We define other relations over our universe in a similar way as we have done for the -equivalence relation. For instance, the notOccurBind relation holds if some given variable does not occur in any binder position within a term. In this relation we discard the name sort information. We do so to simplify our next development as we will explain later. We find useful to extend this relation to lists of variables, named as ListNotOccurBind, which holds if all the variables in a given list do not occur in any binder position (associated with any sort) in a term. Using this relation we are able to prove the lemma stated in Figure 14. This lemma states that the fold with context principle is -compatible on its two arguments if the provided function is -compatible and well-behaved with respect to name-swapping. Note that this lemma extends the one given before in Figure 13, although it requires extra freshness premises, and that the folded function is preserved under name-swapping.

[GenericProgramming/Alpha.tex]lemmafoldCtxalpha

Figure 14: Fold context -compatibility property.

4.1 Alpha Fold

We are now able to introduce a fold operation that works at the level of -equivalence classes of terms, that is, it only defines -compatible functions. First, we introduce the function bindersFreeElem that takes a list of variables  and an element , and returns an element -equivalent to whose binders are not in the given list. This function will be useful to reproduce the BVC, which basically states that we can always pick a term with its binders fresh from a given context, which in this function is represented as a list of variables. We prove that this function has the important property of being strongly -compatible, i.e. that it returns the same result for -convertible terms.

[GenericProgramming/AlphaInduction.tex]bindersfreealphaelem

Based on this function, we next directly implement the -fold principle as an instance of the fold with context function.

[GenericProgramming/AlphaInduction.tex]foldCtxalpha

This iteration principle first finds a fresh term for a given context , and then directly applies the fold operation over it. We developed this iteration principle following a different approach from the one taken in our previous work [8], where we renamed the binders during the fold traverse. Instead, we chose to separate these two stages in order to reuse the previously defined fold operation and its properties.

We can now properly justify the name “alpha” given to the introduced iteration principle. Firstly, as bindersFreeElem returns syntactical equal terms when applied to -convertible terms, we have that our function is trivially strong -compatible on its last term argument. Secondly, as a direct consequence from the lemma already proved for our iteration principle foldCtx in Figure 13, this new principle inherits its -compatibility in its context argument from foldCtx, given that the function received is also -compatible on its arguments. Thus, the presented iteration principle works at the -equivalence classes level when the given function works at the same level.

Now we can derive the capture avoiding substitution operation for the lambda calculus example by a direct application of the introduced -fold principle. In fact this definition is exactly the same as the one given before for the naive substitution, but using now the -fold operation instead of the fold one.

[GenericProgramming/Examples/LambdaCalculus.tex]subst

Substitution lemmas stating that substitution is well-behaved with respect to -conversion are inherited from the -compatibility of the iteration principle, only requiring the -compatibility property of the substaux function. As this auxiliary function is not recursively defined, this proof is just a simple case analysis, while the proof involving the recursive data-type traversal is resolved at the generic level.

Next lemma in Figure 15 relates the presented -fold principle with the previously defined one, giving sufficient conditions under which the two principles return -convertible terms. First, the folded function must be -compatible on its two arguments, and also well-behaved with respect to name-swapping. Secondly, we need a freshness premise stating that the free variables in the context do not occur bound in the applied term.

[GenericProgramming/AlphaInduction.tex]lemmafoldCtxalpha

Figure 15: Fold and -fold relations.

We can instantiate this lemma to the -calculus to get sufficient conditions under which the two presented substitution operations are -convertible. Its proof requires two lemmas about the substaux function, one stating that it is -compatible, and the other one stating that it is well-behaved under name-swapping. Both lemmas were already used in previous proofs.

4.2 Alpha Induction Principle

In this section we generalise previous works [8, 7], developing an -induction principle for -compatible predicates. Our presentation introduces an explicit premise about the -compatibility of the predicate being proved, which in general is not explicitly mentioned in informal developments, but is certainly required to ensure that the predicate in question is actually about abstract terms, i.e. not dependent on the choice of bound names. Hence, to prove some property over any term, this principle requires the user to prove the property only for terms with fresh enough binders, i.e. distinct from the variables in some given context, as is usually done under the BVC. We derive this principle following a procedure similar to the one used to infer the principle in Section 2.3. We show below the interesting recursive and binder cases, the remaining ones being equivalent to those presented in Figure 6. We define an auxiliary function fihalpha, which transforms a given predicate  over a datatype μ F to a predicate over the datatype ⟦ G ⟧ (μ F). This predicate states that  holds for every recursive position μ F in a datatype ⟦ G ⟧ (μ F). Besides, it adds freshness premises with respect to some given variables list  in the recursive and binder cases of its definition: In the binder case, it states that the binder is not in the given list , while, in the recursive case, it states that no variable in  occurs in a binder position in the recursive subterm .

[GenericProgramming/AlphaInduction.tex]alphainductionhypotheses [GenericProgramming/AlphaInduction.tex]alphainductionhypothesescases

We state this principle in Figure 16. Its proof is similar to the -fold principle’s proof. We firstly use the function bindersFreeElem (from Section 4.1) over the parameter  and the freshness context  to get an -equivalent term  with binders not occurring in the list . Then we apply the primitive induction principle (Figure 7) over the fresh term  to prove the following predicate :

Finally, we apply the proof of predicate  to the term and its freshness hypothesis to obtain that  must hold. Hence, as the predicate  is -compatible, and , we get that  should also hold.

[GenericProgramming/AlphaInduction.tex]alphainductionprinciple

Figure 16: Alpha induction principle.

The proof of  is done using an auxiliary lemma which recursively reconstructs a proof of fihalpha  given that fih  holds and that the binders of  do not occur in the context . This proof is just a generalisation of the one already presented in [7] for an equivalent -induction principle for -calculus. In this previous work we were also able to prove the Church-Rosser theorem for the -calculus using this equivalent induction principle. Therefore, we conjecture that following the same procedure we would be able to achieve the confluence of -reduction result within our generic framework. However, we sketch another approach in next section to prove the substitution composition lemma, a crucial lemma in the confluence proof.

5 Codification of a BVC proof technique.

In Figure. 17 we show a result that validates the BVC and usual practices in common pen-and-paper proofs within our generic framework. It states that for any -compatible predicate , we can prove for any term by just proving it for terms whose binders are all different from their own free variables and from the variables in an arbitrary list . As in previous induction principle, this technique requires the -compatibility of the predicate being proved.

[GenericProgramming/AlphaInduction.tex]alphaproof

Figure 17: BVC proof principle.

To prove for arbitrary , we proceed as follows: We first find a fresh enough term  such that    using the function bindersFreeElem. Then, we can use the hypothesis for the fresh term  to derive that  holds. Finally, must also hold, as is -compatible. We do not show the code of the proof, since it is similar to others previously presented.

Next we illustrate the use of this result to prove the substitution composition lemma for System F. First, we prove this lemma for the naive substitution operation. Next we introduce the property to be proved. Note that an extra freshness premise stating that  does not occur bound in the term is required, since we use the naive substitution.

[GenericProgramming/Examples/SystemF.tex]substnaivecompositionpredicate

The proof is done using the structural induction principle (Figure 7). We show below the interesting abstraction case:

[GenericProgramming/Examples/SystemF.tex]substncompositionabstractioncase

This equational proof is constructed following the usual pen-and-paper practice: First we push the substitution inside the abstraction. Then, by the induction hypothesis we know that the composition of substitutions in the abstraction bodies are -convertible, and hence we are able to prove that the entire abstraction is -convertible too, using the auxiliary lemma lemma∼+B. Finally, we push back the substitutions outside the abstraction to conclude the proof.

Now we prove the substitution composition lemma for the capture-avoiding substitution operation using the introduced -proof technique. We begin by defining the functor describing a triple of terms TreeTermF. Then, we introduce the predicate PSComp over triples, stating the composition lemma for the substitution.

[GenericProgramming/Examples/SystemF.tex]substcompositionpredicate

We prove that PSComp is -compatible with respect to triples of terms by a direct equational proof using basically the previous substitution lemmas. In Figure 18 we show the core of the proof. It uses the preceding substitution lemmas to replace the classical substitution operations with the naive ones. This can be done because we have freshness premises stating that in the introduced context of triples all binders are different from the free variables in the involved terms, and also from variables and . Finally, we work in very much the same way as we did at the beginning to recover the classical substitutions from the naive ones. There are many auxiliary lemmas and boilerplate code concerning the freshness premises involved in the last proof which we do not show in this presentation. These are hidden inside auxiliary lemmas as: y:fvL-NB-M[x≔N]ₙ and y:fvL-NB-N occurring in the proof. The first of these lemmas, for instance, proves that neither the variable  nor the free variable binding in  occur bound in , which is easy to verify from the freshness premises. However, we believe further work is necessary to automatise some of these proofs, or even rewriting the freshness relations in order to alleviate its handling.

Finally, we can use the introduced -proof principle with the previous proof obligations to finish the proof. Note how, by applying the -proof technique to a triple of terms, we were able to get sufficient freshness premises to develop a proof similar in structure to pen-and-paper ones in a direct manner. This is possible because in our generic framework we can state the -equivalence of any structure (triples in this case), and not just language terms.

[GenericProgramming/Examples/SystemF.tex]substitutioncompositionproof

Figure 18: Proof of Substitution composition lemma.

6 Conclusions

We address the formalisation of a general first order named syntax with multi-sorted binders by applying a combination of generic programming and nominal techniques to derive fold operations, name-swapping, the -conversion relation, and -induction/iteration principles for any language abstract syntax with binders. We derive the -calculus and System F as instances of the introduced general framework. For these examples we derive both the naive and the capture-avoiding substitutions as direct instances of the corresponding fold and -fold principles. We directly inherit the classical substitution lemmas for the -conversion, and the good behavior of substitution under the name-swapping from fold properties already proved at the generic level. We prove a lemma stating sufficient conditions under which the fold and -fold functions are -equivalent. Therefore, as substitution operations are direct instances of these iteration principles, we get in an almost free manner a result about the relation between the naive and the capture-avoiding substitution operations for the -calculus and System F. This result is particularly useful in the last proof, which is conducted using the introduced -proof technique, that enables us to mimic the BVC in a generic setup.

Our work uses generic programming techniques to develop the meta-theory of abstract syntax with binders in a general way as in related works. But we choose to maintain names for binders like as usually done in informal practice. On the other hand, contrary to the historical standpoint, following ideas in [10], we give -conversion a more fundamental role than that of the definition of substitution. Indeed, we verify that the name-swapping is powerful enough to define a theory of structural induction/recursion modulo  in a general way.

We generalise the -recursion/induction principles developed in [8, 7]. In these previous works we renamed binders within the fold traversal. Instead, in this work we separate these stages, managing to reuse the fold operation and its properties. We also present an -proof technique which is not based on an induction principle as in the previous works, and thus can be used to prove properties over relations or composite datatypes. This is the case in the proof of the substitution composition lemma, where it is used to obtain freshness premises over a triple of terms, which is possible because of the generic character of the approach, allowing us to state the -equivalence or freshness premises over any composite datatype; that is, we are able to state freshness in any mathematical context, thus reflecting the BVC more accurately.

Generic programming techniques are capable of further improvements as the one considered in [9], where a more modular assembly is introduced, enabling a more structured approach to the reuse of meta-theory formalisations through the composition of modular inductive definitions and proofs. The present work does not directly support a modular reuse, but it would be interesting to explore this improvement.

In [2] Reynold’s parametricity theory is used to prove the -compatibility property of a big step semantics using reflection within Coq. They introduce a lambda calculus terms interface, and by a formalisation of Reynold’s parametricity, they prove that polymorphic functions (over this interface) applied to related inputs produces related outputs. Then, given two concrete implementations of their lambda terms interface, one with de Brujin syntax (where α-convertible are syntaticaly equal), and another one nominal, they are able to get as a "free theorem" that on α-convertible inputs, the big step function produces α-convertible outputs in the nominal syntax. It remains as future work to study how our generic framework could be used to internalise this kind of "free theorems" by introducing a de Brujin interpretation to our universe, and then translate results between interpretations.

Acknowledgements. We gratefully acknowledge DoD support under award FA9550-16-1-0082 (MURI Program).

References