Quantitative aspects of linear and affine closed lambda terms
Pierre Lescanne (LIP)

TL;DR
This paper provides combinatorial counts and generation algorithms for various classes of closed affine and linear lambda-terms and their normal forms, based on size measurements and context data structures.
Contribution
It introduces formulas for counting and generating closed affine and linear lambda-terms and their normal forms using context-based data structures.
Findings
Formulas for counting lambda-terms and normal forms by size.
Algorithms for generating all terms of a given size.
Use of context data structures for term enumeration.
Abstract
Affine -terms are -terms in which each bound variable occurs at most once and linear -terms are -terms in which each bound variables occurs once. and only once. In this paper we count the number of closed affine -terms of size , closed linear -terms of size , affine -normal forms of size and linear -normal forms of ise , for different ways of measuring the size of -terms. From these formulas, we show how we can derive programs for generating all the terms of size for each class. For this we use a specific data structure, which are contexts taking into account all the holes at levels of abstractions.
Peer Reviews
No public reviews on file for this paper yet. If you reviewed it on a platform where reviews are public (OpenReview, ICLR, NeurIPS, ICML), you can paste yours below so the community can read it here.
Code & Models
Videos
No videos yet. Explain this paper in a talk, walkthrough, or lecture? Add one.
Taxonomy
TopicsRough Sets and Fuzzy Logic · Logic, programming, and type systems · Advanced Algebra and Logic
Quantitative aspects of
linear and affine closed lambda terms
Pierre Lescanne
University of Lyon
École normale supérieure de Lyon
LIP (UMR 5668 CNRS ENS Lyon UCBL INRIA)
46 allée d’Italie, 69364 Lyon, France
Abstract
Affine -terms are -terms in which each bound variable occurs at most once and linear -terms are -terms in which each bound variable occurs once. and only once. In this paper we count the number of closed affine -terms of size , closed linear -terms of size , affine -normal forms of size and linear -normal forms of size , for different ways of measuring the size of -terms. From these formulas, we show how we can derive programs for generating all the terms of size for each class. The foundation of all of this is specific data structures, which are contexts in which one counts all the holes at each level of abstractions by ’s.
Keywords: Lambda calculus, combinatorics, functional programming
1 Introduction
The -calculus [1] is a well known formal system designed by Alonzo Church [8] for studying the concept of function. It has three kinds of basic operations: variables, application and abstraction (with an operator which is a binder of variables). We assume the reader familiar with the -calculus and with de Bruijn indices.111If the reader is not familiar with the -calculus, we advise him to read the introduction of [15], for instance.
In this paper we are interested in terms in which bound variables occur once. A closed -term is a -term in which there is no free variable, i.e., only free variables. An affine -term (or BCK term) is a term in which bound variables occur at most once. A linear -term (or BCI term) is a -term in which bound variables occur once and only once.
In this paper we propose a method for counting and generating (including random generation) linear and affine closed -terms based on a data structure which we call SwissCheese because of its holes. Actually we count those -terms up-to -conversion. Therefore it is adequate to use de Bruijn indices [11], because a term with de Bruijn indices represents an -equivalence class. An interesting aspect of these terms is the fact that they are simply typed [17, 16]. For instance, generated by the program of Section 5 6, there are linear terms of natural size :
[TABLE]
[TABLE]
written with explicit variables
[TABLE]
[TABLE]
[TABLE]
[TABLE]
and there are affine terms of natural size :
[TABLE]
[TABLE]
[TABLE]
The Haskell programs of this development are on GitHub: https://github.com/PierreLescanne/CountingGeneratingAfffineLinearClosedLambdaterms.
Notations
In this paper we use specific notations.
Given a predicate , the Iverson notation written is the function taking natural values which is if is true and which is [math] if is false.
Let be the -tuple . In Section 5, we consider also infinite tuples. Thus is the sequence . Notice in the case of infinite tuples, we are only interested in infinite tuples equal to [math] after some index.
- •
is the length of , which we write also
- •
The -tuple is written . is the infinite tuple made of [math]’s.
- •
The increment of a -tuple at is:
[TABLE]
- •
Putting an element as head of a tuple is written
[TABLE]
tail removes the head of a tuple:
[TABLE]
- •
is the componentwise addition on tuples.
2 SwissCheese
The basic concept is this of -SwissCheese or Swisscheese of characteristic or simply SwissCheese if there is no ambiguity on . A -SwissCheese or a SwissCheese of characteristic , where is of length ) is, a -term with holes at levels, which are all counted, using . The levels of holes are ,… . A hole is meant to be a location for a variable at level , that is under ’s. According to the way bound variables are inserted when creating abstractions (see below), we consider linear or affine SwissCheeses. The holes have size [math]. An -SwissCheese or a SwissCheese of characteristic has holes at level [math], holes at level , … holes at level . Let (resp. ) count the linear (resp. the affine) -SwissCheese of size . and if is finite, , for , and for . (resp. ) counts the closed linear (resp. the closed affine) -terms.
2.1 Growing a SwissCheese
Given two SwissCheeses, we can build a SwissCheese by application like in Fig 1.
In Fig. 1, is a -SwissCheese, is a -SwissCheese and is a -SwissCheese. Said otherwise, has characteristic , has characteristic and has characteristic . According to what we said, has characteristic as well as characteristic (a tuple starting with , followed by , followed by infinitely many [math]’s). We could also say that has characteristic and has characteristic making a binary operation on SwissCheeses of length whereas previously we have made a binary operation on SwissCheeses of length . In other words, when counting SwissCheeses of characteristic , the trailing [math]’s are irrelevant. In actual computations, we make the lengths of characteristics consistent by adding trailing [math]’s to too short ones.
Given a SwissCheese, there are two ways to grow a SwissCheese to make another SwissCheese by abstraction.
We put a on the top of a -SwissCheese . This increases the levels of the holes: a hole becomes a hole . is a -SwissCheese. See Fig 2 on the left. This way, no index is bound by the top , therefore this does not preserve linearity (it preserves affinity however). Therefore this construction is only for building affine SwissCheeses, not for building linear SwissCheeses. In Figure 2 (left), we colour the added in blue and we call it abstraction with no binding. 2. 2.
In the second method for growing a SwissCheese by abstraction, we select first a hole , we top the SwissCheese by a , we increment the levels of the other holes and we replace the chosen hole by . In Figure 2 (right), we colour the added in green and we call it abstraction with binding.
2.2 Measuring SwissCheese
We considers several ways of measuring the size of a SwissCheese derived from what is done on -terms. In all these sizes, applications and abstractions have size and holes have size [math]. The differences are in the way variables are measured.
- •
Variables have size [math], we call this variable size [math].
- •
Variables have size , we call this **variable size **.
- •
Variables (or de Bruijn indices) have size , we call this natural size.
3 Counting linear closed terms
We start with counting linear terms since they are slightly simpler. We will give recursive formulas first for the numbers of linear SwissCheeses of natural size with holes set by , then for the numbers of linear SwissCheeses of size , for variable size [math], with holes set by , eventually for the numbers of linear SwissCheeses of size , for variable size , with holes set by . When we do not want to specify a chosen size, we write only without superscript.
3.1 Natural size
First let us count linear SwissCheeses with natural size. This is given by the coefficient which has two arguments: the size of the SwissCheese and a tuple which specifies the number of holes of each level. In other words we are interested in the quantity . We assume that the length of is , greater than .
whatever size is considered, there is only one SwissCheese of size [math] namely . This means that the number of SwissCheeses of size [math] is if and only if :
[TABLE]
** and application**
if a -term of size has holes set by and is an application, then it is obtained from a term of size with holes set by and a term of size with holes set by , with :
[TABLE]
** and abstraction with binding**
consider a level , that is a level of hole . In this hole we put a term of size . There are ways to choose a hole . Therefore there are SwissCheeses which are abstractions with binding in which a has been replaced by the de Bruijn index among SwissCheeses, where is in which is decremented. We notice that this refers only to an starting with [math]. Hence by summing over and adjusting , this part contributes as:
[TABLE]
to .
We have the following recursive definitions of :
[TABLE]
Numbers of closed linear terms with natural size are given in Figure 3.
3.2 Variable size [math]
The only difference is that the inserted de Bruijn index has size [math]. Therefore we have where we had for natural size. Hence the formulas:
[TABLE]
The sequence of the numbers of closed linear terms is which is sequence A062980 in the On-line Encyclopedia of Integer Sequences with [math]’s at even indices.
3.3 Variable size
The inserted de Bruijn index has size . We have where we had for natural size.
[TABLE]
As noticed by Grygiel et al. [13] (§ 6.1) There are no linear closed -terms of size and . However for the values we get the sequence: which is again sequence A062980 of the On-line Encyclopedia of Integer Sequences.
4 Counting affine closed terms
We have just to add the case * and abstraction without binding*. Since no index is added, the size increases by . The numbers are written , , , and when the size does not matter. There are -SwissCheeses of size that are abstraction without binding. We get the recursive formulas:
4.1 Natural size
[TABLE]
The numbers of closed affine size with natural size are given in Figure 4.
4.2 Variable size [math]
[TABLE]
The sequence of the numbers of affine closed terms for variable size [math] is
[TABLE]
It does not appear in the On-line Encyclopedia of Integer Sequences. It corresponds to the coefficients of the generating function where
[TABLE]
4.3 Variable size
[TABLE]
The sequence of the numbers of affine closed terms for variable size is
[TABLE]
This is sequence A281270 in the On-line Encyclopedia of Integer Sequences. However it corresponds to the coefficient of the generating function where is the solution of the functional equation:
[TABLE]
Notice that this corrects the wrong assumptions of [13] (Section 6.2).
5 Generating functions
Consider families of generating functions indexed by , where is an infinite tuple of naturals. In fact, we are interested in the infinite tuples that are always [math], except a finite number of indices, in order to compute , which corresponds to closed -terms. Let stands for the infinite sequences of variables and stands for and stand for . We consider the series of two variables and or double series associated with :
[TABLE]
Natural size
is associated with the numbers of closed linear SwissCheeses for natural size:
[TABLE]
is the generating function for the closed linear -terms. is the double series associated with and is solution of the equation:
[TABLE]
is the generating function of closed linear -terms.
For closed affine SwissCheeses we get:
[TABLE]
is the generating function for the closed linear -terms. is the double series associated with and is solution of the equation:
[TABLE]
is the generating function of closed affine -terms.
Variable size [math]
is associated with the numbers of closed linear SwissCheeses for variable size [math]:
[TABLE]
is the generating function for the closed linear -terms. is the double series associated with and is solution of the equation:
[TABLE]
is the generating function of closed linear -terms.
For closed affine SwissCheeses we get:
[TABLE]
is the generating function for the affine linear -terms. is the double series associated with and is solution of the equation:
[TABLE]
is the generating function of closed linear -terms.
Variable size
The generating functions for are:
[TABLE]
Then we get as associated double series :
[TABLE]
6 Effective computations
The definition of the coefficients and others is highly recursive and requires a mechanism of memoization. In Haskell, this can be done by using the call by need which is at the core of this language. Assume we want to compute the values of until a value upBound for . We use a recursive data structure:
data Mem = Mem [Mem] | Load [Integer]
in which we store the computed values of a function
a :: Int -> [Int] -> Integer
In our implementation the depth of the recursion of Mem is limited by upBound, which is also the longest tuple for which we will compute . Associated with Mem there is a function
access :: Mem -> Int -> [Int] -> Integer access (Load l) n [] = l !! n access (Mem listM) n (k:m) = access (listM !! k) n m
The leaves of the tree memory, corresponding to Load, contains the values of the function:
memory :: Int -> [Int] -> Mem memory 0 m = Load [a n (reverse m) | n<-[0..]] memory k m = Mem [memory (k-1) (j:m) | j<-[0..]]
The memory relative to the problem we are interested in is
theMemory = memory (bound) []
and the access to theMemory is given by a specific function:
acc :: Int -> [Int] -> Integer acc n m = access theMemory n m
Notice that a and acc have the same signature. This is not a coincidence, since acc accesses values of a already computed. Now we are ready to express a:
a 0 m = iv (head m == 1 && all ((==) 0) (tail m)) a n m = aAPP n m + aABSwB n m + aABSnB n m
aAPP counts affine terms that are applications:
aAPP n m = sum (map (((q,r),(k,nk))->(acc k q)*(acc nk r)) (allCombinations m (n-1)))
where allCombinations returns a list of all the pairs of pairs such and of pairs such that . aABSwB counts affine terms that are abstractions with binding.
aABSwB n m | head m == 0 = sum [aABSAtD n m i |i<-[1..(n-1)]] | otherwise = 0
aABSAtD counts affine terms that are abstractions with binding at level :
aABSAtD n m i = (fromIntegral (1 + m!!i))*(acc (n-i-1) (tail (inc i m) ++ [0]))
aABSnB counts affine terms that are abstractions with no binding:
aABSnB n m | head m == 0 = (acc (n-1) (tail m ++ [0])) | otherwise = 0
Anyway the efficiency of this program is limited by the size of the memory, since for computing , for instance, we need to compute for about values.
7 Generating affine and linear terms
By relatively small changes it is possible to build programs which generate linear and affine terms. For instance for generating affine terms we get.
amg :: Int -> [Int] -> [SwissCheese] amg 0 m = if (head m == 1 && all ((==) 0) (tail m)) then [Box 0] else [] amg n m = allAPP n m ++ allABSwB n m ++ allABSnB n m
allAPP :: Int -> [Int] -> [SwissCheese] allAPP n m = foldr (++) [] (map (((q,r),(k,nk))-> appSC (cartesian (accAG k q) (accAG nk r)) (allCombinations m (n-1)))
allABSAtD :: Int -> [Int] -> Int -> [SwissCheese] allABSAtD n m i = foldr (++) [] (map (abstract (i-1)) (accAG (n - i - 1) (tail (inc i m) ++ [0])))
allABSwB :: Int -> [Int] -> [SwissCheese] allABSwB n m | head m == 0 = foldr (++) [] [allABSAtD n m i |i<-[1..(n-1)]] | otherwise = []
allABSnB :: Int -> [Int] -> [SwissCheese] allABSnB n m | head m == 0 = map (AbsSC . raise) (accAG (n-1) (tail m ++ [0])) | otherwise = []
memoryAG :: Int -> [Int] -> MemSC memoryAG 0 m = LoadSC [amg n (reverse m) | n<-[0..]] memoryAG k m = MemSC [memoryAG (k-1) (j:m) | j<-[0..]]
theMemoryAG = memoryAG (upBound) []
accAG :: Int -> [Int] -> [SwissCheese] accAG n m = accessSC theMemoryAG n m
From this, we get programs for generating random affine terms or random linear terms as follows: if we want a random closed linear term of a given size , we throw a random number, say , between and and we look for the in the list of all the closed linear terms of size . Haskell laziness mimics the unranking. Due to high requests in space, we cannot go further than the random generation of closed linear terms of size and closed affine terms of size . There are similar programs for generating all the terms of size for variable size [math] and variable size .
8 Normal forms
From the method used for counting affine and linear closed terms, it is easy to deduce method for counting affine and linear closed normal forms. Like before, we use SwissCheeses. In this section we consider only natural size.
8.1 Natural size
Affine closed normal forms
Let us call the numbers of affine SwissCheeses with no -redex and the numbers of neutral affine SwissCheeses, i.e., affine SwissCheeses with no -redexes that are sequences of applications starting with a de Bruijn index. In addition we count:
- •
the number of affine SwissCheeses with no -redex which are abstraction with a binding of a de Bruijn index,
- •
the number of affine SwissCheeses with no -redex which are abstraction with no binding.
[TABLE]
where
[TABLE]
and
[TABLE]
and
[TABLE]
There are two generating functions, and , which are associated to and :
[TABLE]
Linear closed normal forms
Let us call the numbers of linear SwissCheeses with no -redex and the numbers of neutral linear SwissCheeses, linear SwissCheeses with no -redexes that are sequences of applications starting with a de Bruijn index. In addition we count the number of linear SwissCheeses with no -redex which are abstraction with a binding of a de Bruijn index.
[TABLE]
where
[TABLE]
and
[TABLE]
with the two generating functions:
[TABLE]
We also deduce programs for generating all the closed affine or linear normal forms of a given size from which we deduce programs for generating random closed affine or linear normal forms of a given size. For instance, here are three randoms linear closed normal forms (using de Bruijn indices) of natural size :
[TABLE]
8.2 Variable size [math]
Linear closed normal forms
A little like previously, let us call the numbers of linear SwissCheeses with no -redex and the numbers of neutral linear SwissCheeses, linear SwissCheeses with no -redexes that are sequences of applications starting with a de Bruijn index. In addition we count the number of linear SwissCheeses with no -redex which are abstraction with a binding of a de Bruijn index. We assume that the reader knows now how to proceed.
[TABLE]
where
[TABLE]
[TABLE]
and the two generating functions:
[TABLE]
With no surprise we get for the sequence:
[TABLE]
mentioned by Zeilberger in [19] and listing the coefficients of the generating function .
We let the reader deduce how to count closed affine normal forms for variable size [math] and closed linear and affine normal forms for variable size alike. Notice that the Haskell programs are on the GitHub site.
9 Related works and Acknowledgement
There are several works on counting -terms, for instance on natural size [3, 2], on variable size [5, 10, 18], on variable size [math] [14], on affine terms with variable size 1 [7, 6], on linear -terms [21, 19, 20], also on a size based binary representation of the -calculus [15] (see [12] for a synthetic view of both natural size and binary size).
The basic idea of this work comes from a discussion with Maciej Bendkowski, Olivier Bodini, Sergey Dovgal and Katarzyna Grygiel, I thank them as I thank Noam Zeilberger for interactions.
10 Conclusion
This presentation shares similarity with this of [14, 15, 4]. Instead of considering the size and the bound of free indices like in expressions of the form:
[TABLE]
here we replace by the characteristic . We can imagine a common framework. On another hand, as noticed by Paul Tarau, this approach has features of dynamic programming [9], which makes it somewhat efficient.
Data
In the appendix, we give the first values of , , and .
The reference list from the paper itself. Each links out to its DOI / PubMed record.
- 1[1] Henk P. Barendregt. The Lambda-Calculus, its syntax and semantics . Studies in Logic and the Foundation of Mathematics. Elsevier Science Publishers B. V. (North-Holland), Amsterdam, 1984. Second edition.
- 2[2] Maciej Bendkowski, Katarzyna Grygiel, Pierre Lescanne, and Marek Zaionc. Combinatorics of λ 𝜆 \lambda -terms: a natural approach. Co RR , abs/1609.07593, 2016.
- 3[3] Maciej Bendkowski, Katarzyna Grygiel, Pierre Lescanne, and Marek Zaionc. A natural counting of lambda terms. In Rusins Martins Freivalds, Gregor Engels, and Barbara Catania, editors, SOFSEM 2016: Theory and Practice of Computer Science - 42nd International Conference on Current Trends in Theory and Practice of Computer Science, Harrachov, Czech Republic, January 23-28, 2016, Proceedings , volume 9587 of Lecture Notes in Computer Science , pages 183–194. Springer, 2016.
- 4[4] Maciej Bendkowski, Katarzyna Grygiel, and Paul Tarau. Boltzmann samplers for closed simply-typed lambda terms. In Yuliya Lierler and Walid Taha, editors, Practical Aspects of Declarative Languages - 19th International Symposium, PADL 2017, Paris, France, January 16-17, 2017, Proceedings , volume 10137 of Lecture Notes in Computer Science , pages 120–135. Springer, 2017.
- 5[5] Olivier Bodini, Danièle Gardy, and Bernhard Gittenberger. Lambda terms of bounded unary height. In Proceedings of the Eighth Workshop on Analytic Algorithmics and Combinatorics , pages 23–32, 2011.
- 6[6] Olivier Bodini, Danièle Gardy, Bernhard Gittenberger, and Alice Jacquot. Enumeration of generalized BCI lambda-terms. Electr. J. Comb. , 20(4):P 30, 2013.
- 7[7] Olivier Bodini, Danièle Gardy, and Alice Jacquot. Asymptotics and random sampling for BCI and BCK lambda terms. Theor. Comput. Sci. , 502:227–238, 2013.
- 8[8] Alonzo Church. A formulation of the simple theory of types. Journal of Symbolic Logic , 5:56–68, 1940.
