A Verified Cost Model for Call-By-Push-Value
Abstract
The call-by-push-value -calculus allows for syntactically specifying the order of evaluation as part of the term language. Hence, it serves as a unifying language for embedding various evaluation strategies including call-by-value and call-by-name. Given the impact of call-by-push-value, it is remarkable that its adequacy as a model for computational complexity theory has not yet been studied. In this paper, we show that the call-by-push-value -calculus is reasonable for both time and space complexity. A reasonable cost model can encode other reasonable cost models with polynomial overhead in time and constant factor overhead in space. We achieve this by encoding call-by-push-value -calculus into Turing machines, following a simulation strategy by Forster et al.; for the converse direction, we prove that Levy’s encoding of the call-by-value -calculus has reasonable complexity bounds. The main results have been formalised in the HOL4 theorem prover.
Keywords and phrases:
lambda calculus, formalizations of computational models, computability theory, HOL, call-by-push-value reduction, time and space complexity, abstract machinesCopyright and License:
2012 ACM Subject Classification:
Theory of computation Lambda calculusSupplementary Material:
Software (Mechanised Proof): https://github.com/ZhuoZoeyChen/cbpv-reasonable-HOL/ [5]archived at
swh:1:dir:df18377e9fa5e35255f2687ad66ddbc2f010b934
Acknowledgements:
We thank Yannick and Fabian for taking the time to meet with us and discuss their work on the weak call-by-value -calculus. We are also grateful to the anonymous reviewers for their valuable feedback.Editors:
Yannick Forster and Chantal KellerSeries and Publisher:
Leibniz International Proceedings in Informatics, Schloss Dagstuhl – Leibniz-Zentrum für Informatik
1 Introduction
The -calculus [7] is a fundamental model of computation that represents functions as abstractions over variables. It provides a foundation for computability, mathematical logic, and functional programming. Functional programming supports a concise, declarative style of programming that is ideal for reasoning about functional correctness properties.
Besides functional correctness, another important property of a program is its computational complexity. It addresses the vital questions: How fast does my program produce an output? How much space will my program use in order to produce that output?
In complexity analysis, we describe the asymptotic behaviour of cost functions that model the cost of the program mathematically. But where do cost functions come from? In practice they are often constructed in an ad hoc manner with no formal connection to any program semantics. Cost models bridge that gap.
Creating cost models for functional programming languages is thus an essential topic. It is also a significant challenge due to the abstract nature of functional programming. As -calculus is the basis of functional programming languages, a vital question is whether we can create cost models for the -calculus. There has been a large body of research [18, 8, 2, 1, 11, 12, 3] dedicated to solving this problem. An important parameter in a cost model for the -calculus is the choice of evaluation strategy. One strategy is call-by-value, where function calls are applied once the arguments are fully evaluated, as in Standard ML [23]. Another strategy is call-by-name, where the evaluation of arguments is deferred and the function call happens first.
The call-by-push-value -calculus (CBPV) [19] is a variant of -calculus where the evaluation strategy can be set on a call-by-call basis. In particular, CBPV has syntactic constructs that enable delaying or forcing the evaluation of specific terms. Various evaluation strategies, including call-by-value and call-by-name, can be encoded within this subsuming paradigm.
This high expressive power of CBPV has resulted in a long line of work on the language since its inception [10, 9, 24, 22, 13, 15, 6, 16]. Prior work has studied and extended the calculus [16, 27, 22], related it to other calculi [10, 6, 14], and formalised it [24, 13]. The fine-grained control CBPV provides has proved useful to verify compiler optimisations [24].
There are foundational results that demonstrate that CBPV aids in recurrence extraction, which can in turn be used for analysing the complexity of functional programs, with various evaluation strategies [15].
This demonstrates that CBPV can serve as a basis for further research on analysing the complexity of functional programs with various evaluation strategies. As such, it is vital to establish time and space cost models for CBPV. Naturally, such cost models must satisfy some property that demonstrates that they are fit for purpose.
Reasonable Machines
Turing machines are the standard computational model for complexity theory. They have obvious cost models for time (the number of steps) and space (the number of tape cells used). Cost models are less obvious for -terms, but the readability and convenience of using -terms are higher. Can cost analysis performed in one carry over to the other?
A reasonable cost model [26, 28] answers this question in the positive. Reasonableness is a standard requirement for assessing the suitability of computational models for reasoning about complexity, by relating them to Turing machines (which are considered reasonable by definition). The invariance thesis [28] states that:
“Reasonable machines simulate each other with polynomially bounded overhead in time and constant factor overhead in space”.
Hence the definition of standard complexity classes like P, PSPACE, and EXP are independent of which (reasonable) substrate they are defined on.
Contribution
This paper contributes, to the best of our knowledge, the first reasonable time and space cost models for CBPV. We further provide machine-checked proofs in HOL4 [25] for the core parts thereof. In doing so we build on prior work on formally verified time and space cost models for the weak call-by-value -calculus (WCBV) that was formalised in Coq [17, 11].
Related Work
In 1996, Lawall and Mairson [18] proved that the full -calculus is reasonable for both time and space using the measures total ink used and maximum ink used. But the time measure of total ink used is too general and hard to apply. In 2008, Dal Lago and Martini [8] provided a different time measure for WCBV, which counts the number of -steps while taking account of the size of -redexes. This was further strengthened by Accattoli and Dal Lago [2] in 2016, showing that counting (leftmost-outermost) -steps makes the full -calculus reasonable for time. Continuing on this line, Forster, Kunze, and Roth [11] proved in 2020 that WCBV is reasonable with respect to natural measures, accompanied with a partial formalisation. They define a natural measure to be the number of -reductions for time, and the size of the biggest intermediate term for space. They proved that WCBV is reasonable by interleaving two evaluation strategies: a substitution-based strategy and heap-based strategy, which we adapt and implement for CBPV in our paper. Forster, Kunze, Smolka, and Wuttke [12] provided a complete formalisation in 2021, showing that WCBV is reasonable for time. The complete formal verification of the space invariance thesis for the same calculus still remains open. One limitation of this line of work, as well as ours, is that we do not consider sublinear time or space classes. In contrast, Accattoli, Dal Lago, and Vanoni [3] presented a reasonable space cost model for the -calculus that works for LOGSPACE by using a variant of the Krivine abstract machine. It remains open whether this approach can be extended to CBPV.
CBPV, developed by Levy in 1999 [19], has been increasingly popular in recent decades. There are also various extensions of CBPV, including with stacks [21], with probability [10] and with call-by-need [22]. On the formalisation side, there is a formal equational theory [24] for CBPV; there is another formalisation [13] that includes proofs for its operational, equational, and denotational theory. On the applied side, there are projects such as extracting recurrences [15] using CBPV. There is a similar -calculus called the Bang-calculus [9], which can be regarded as an untyped version of CBPV without any side-effects.
2 Overview
Our goal is to show that CBPV is reasonable. This section is a high-level overview of our proof strategy, which is detailed in Section 6. The main theorems involved are:
Theorem 1 (Turing Machines Simulating CBPV).
Let , . For a CBPV term , if reduces to a normal form in time and space , then one can construct a Turing machine simulating that halts with output simulating , in time and space .
Theorem 2 (CBPV Simulating Turing Machines).
Let , . For a Turing machine that halts with output in time and space , one can construct a CBPV term simulating which can be reduced to a normal form simulating in time and space .
That is, we must model the cost of CBPV using Turing machines and prove that the resulting simulation is cost-bounded (Theorem 1). Moreover, we must show that CBPV provides sufficient expressivity to reasonably simulate any Turing machine (Theorem 2).
Turing Machines Simulating CBPV
Inspired by the strategy used for proving that WCBV is reasonable [11], we verify that CBPV can be simulated by Turing machines with reasonable overhead by using two intermediate abstract machines: the substitution machine (Section 5.2) and the heap machine (Section 5.3).
It is well-known that the -calculus has the size explosion problem, where linear time can lead to exponential growth in space [26]. That is, with -reduction steps, the largest intermediate term can be of size . Turing machines, by contrast, need at least one unit of time to consume one unit of space, so space cost cannot exceed time cost. Hence, if one adopts a substitution-based strategy alone, the overhead in time will be exponential. To solve the size explosion problem, a shared memory structure is required to store values. This motivates why the heap-based strategy is incorporated into our simulation.
But the heap-based strategy has a pointer explosion problem [26], which makes space overhead non-constant. Luckily, size explosion and pointer explosion problems don’t overlap [11], so we can use the heap-based strategy when a size explosion happens, and vice versa.
We formalise the simulation of CBPV by each of the two abstract machines, and verify that it respects the desired bounds in terms of time and space overhead. The cost bounds turn out to be similar to those for WCBV, enabling the adoption of an existing algorithm [11] to obtain a Turing machine simulation by interleaving the substitution and heap machines.
CBPV Simulating Turing Machines
For this direction, we use WCBV as an intermediate model. We first formalise the translation from WCBV to CBPV provided by Levy [19]. We then show that CBPV can simulate WCBV with reasonable time and space overheads. Since WCBV can simulate Turing machines with reasonable overheads [11, Theorem 5.1], we obtain our result for this direction as a corollary.
Formalisation
We verify in HOL4 that our time and space cost models for CBPV have the desired overheads. The formalisation covers all material presented in Section 3, Section 4, Section 5 and Section 6.2. An overview is given in Figure 6 in Section 6. The interleaving strategy, and the connection between abstract machines and Turing machines is done using pen-and-paper proofs adapted from the literature, in Section 6.
3 Call-By-Push-Value -Calculus
The CBPV -calculus [19, 20] allows encoding the order of evaluation as part of the syntax of a program. Hence, it serves as a subsuming paradigm that enables studying evaluation strategies, and combinations thereof, using a single set of reduction rules. Levy provides semantic-preserving translations from call-by-name and call-by-value into CBPV [20].
For simplicity, we use a core fragment of CBPV that is sufficient for demonstrating reasonability. As such we omit, for instance, the general pair types, and instead introduce a simpler double sequencing operation that will be discussed later. Furthermore, while most presentations of CBPV are typed, ours is untyped CBPV. We consider types an orthogonal concern to cost: the well-typed CBPV terms are a strict subset of the untyped CBPV terms, so a cost model for the latter immediately suggests a cost model for the former.
The CBPV terms are defined below as two mutually recursive sets: the values and the computations . The mutual recursion adds some technical difficulties in our formalisation as all relevant functions need to be mutually recursive too. For instance, the substitution function for CBPV, and the compilation function for compiling CBPV terms into programs are both defined mutually recursively, which complicates proofs. To simplify the presentation, we will often use a single overloaded name for two such mutually recursive functions.
Fine-grained control over evaluation can be achieved using the and operators. suspends a computation, and resumes a suspended computation.
Note that we have an extra that is absent in the standard presentation of CBPV. An example of computation is . It allows us to evaluate two computations and and use the results in a third computation . Note that the notation within follows the convention and binds to the right. This can of course be encoded with nested , but at the cost of higher binding depth: . Avoiding this higher binder depth will turn out to be crucial for obtaining constant space overhead in Section 6.2. Including pairs in the language would have solved the problem too, but suffices for our purposes.
We then formalise the big-step cost semantics of closed CBPV provided by Levy [20]; that is, we only consider terms with no free variables at the top level. Similar to the change we made in the syntax, we also add as a special case of the pair type into our semantics.
In order to define the semantics for closed CBPV, we need to first provide a closed substitution function for -reductions. The following function substitutes all the variables with de Bruijn index by in by recursively visiting all the inner terms of :
Note the special cases such as , where we need to increment the targeted variable index accordingly because we are entering extra layers of abstractions. A more special case is , we increment by two for this substitution because needs to leave two free variable names for the two computations and .
We then define time cost and space cost semantics for CBPV. For the time cost semantics, we use a judgement to mean that the computation reduces to in steps. The rules are given in Figure 1.
For space, the judgement says that reduces to with space cost . Note that the time and space cost semantics judgements coincide if the cost annotations are ignored.
We define a size function for CBPV terms as follows. Note that we account for the size of a de Bruijn index in the term size.
Figure 2 gives inference rules of the space cost semantics. It tracks the maximum intermediate term size of an evaluation. For instance, for the case, there are three different evaluation stages: (1). Evaluating ; (2). Evaluating (3). Substituting results and into . The space cost is the maximum size among these stages.
4 Compiling CBPV Terms to Programs
As a first step in bridging the gap between CBPV and Turing machines, we define a flat data structure to represent programs that correspond to CBPV terms. A program is formed of a list of tokens, that are defined as follows:
Definition 3 (Size of Tokens and Programs).
The de Bruijn index counts towards the token size because larger indices require more tape cells to store on Turing machines. The size of a program is simply the sum of the size of its tokens plus (which is the size of the empty program on a Turing machine).
Definitions 4 and 5 define compilation to the substitution and heap machines, respectively.
Definition 4 (Compilation Function for Substitution Machine).
Definition 5 (Compilation Function for Heap Machine).
We define exactly as , except:
We use pairs of delimiter tokens (like and ) when necessary, to preserve the tree structure of the original term. The development of these compilers was fiddly, since the right balance needs to be struck between including enough structure to prevent different subterms from being conflated or evaluated prematurely, yet not too much structure, because extra structure takes space, and must be accounted for in the space cost bound proofs. and make slightly different tradeoffs in this respect. We could change the substitution machine to use , but the overall proof does not require the machines to use the same syntax.
The following lemma is useful for our space cost analysis. It states that the size of a compiled program is linear wrt. term size. (Note that the same lemma also works for .)
Lemma 6 (Program Size Bounds).
We write to state that is the corresponding program for .
Definition 7 (Program-Term Correspondence).
holds if .
5 Abstract Machines
Recall from Section 2 that our proof strategy relies on interleaving two simulation strategies to achieve reasonability in time and space. The substitution-based strategy has reasonable overhead for space, but not for time due to the size explosion problem. The heap-based strategy has reasonable overhead for time, but not for space due to the pointer explosion problem. These two explosion problems do not occur at the same time. Thus, by interleaving the respective Turing machines for each of these two strategies, we can obtain a reasonable simulation. In order to achieve this, we first implement two abstract machines that represent these two strategies respectively in this section. We then construct the corresponding Turing machines and finish the rest of the proofs in Section 6. Note that the size of intermediate terms and the complexity differs between the abstract machines and their corresponding Turing machines.
In this section, we first introduce an auxiliary extraction function that is used by both abstract machines (Section 5.1). We then introduce the substitution machine (Section 5.2) and the heap machine (Section 5.3), and investigate their cost in relation to CBPV.
5.1 Extraction Function
For each pair of delimiter tokens, we define a function to scan a program until the corresponding end delimiter. To simplify the presentation, we overload to account for all operands. The idea is that strips the argument body out of and returns it as , where is the rest of the program. We show the extraction function for - below. The intuition is similar to finding matching parentheses pairs. When is applied to a well-formed , we have , where has balanced - pairs.
Definition 8 (Extraction Function for - ).
where:
5.2 Substitution Machine
In this section, we develop a machine that implements a substitution-based evaluation strategy. Before diving into the transition rules, we need a helper function that is used to prevent empty lists from accumulating on the stack. It is defined recursively as follows:
The substitution machine performs substitutions immediately as they appear at the top of the current stacks. The machine state consists of two stacks: the task stack and the value stack. In the initial state, the value stack is empty and the task stack contains the for a CBPV computation . On successful termination, a final value is produced on the value stack, and the task stack is empty. Note that the value stack (despite its name) will sometimes contain computations in non-final states. An alternative presentation would be to add an extra stack for suspended computations, but we found no need for this.
Substitution on programs, written, is similar to that for CBPV terms (Section 3); its definition is elided. Figure 3 shows the transition rules for the substitution machine. The three columns represent the task stack, the value stack, and the assumptions. Each represents one transition step, where the row above represents the current state of the machine, and the row on the same level as represents the next state of the machine after the transition. For example, the transition rule for strips one layer of - off the task stack and places it on the value stack (thus suspending it). Note that the transition rules for and can strip components from the value stack directly without the extraction function . For instance, in the rule, is just the first element on the value stack. We can strip it with a simple list operation. Furthermore, since there is no extra subsequent programs after in , we can obtain by removing and using simple list operations.
The transition rule for is not strictly necessary: we only consider closed terms, so the rule will never be exercised when running the compilation output. Nonetheless, including it appears to make the proofs more ergonomic, by making it unnecessary to carry around a closedness side condition. For example, consider the useful technical lemma
which holds unconditionally when the rule is present in the substitution machine semantics. If we remove the rule, it only holds when is a thunk.
Multiple transitions are written , where is the current task stack and is the current value stack. We obtain a new state after applying the transition rules times on the current state , with the size of the biggest intermediate state being ½. We elide or when irrelevant. We write to represent or more transition steps.
The substitution machine simulates CBPV with constant time and space overhead:
Lemma 9 (Substitution Machine Time Simulation).
If , then there exists such that where and and .
Proof.
By rule induction on the big-step semantics of CBPV.
Lemma 10 (Substitution Machine Space Simulation).
If then there exists such that , where and and .
Proof.
Similar to the time simulation proof, we induct on the structure of the big-step semantics of CBPV and show that this theorem is true for all the transition rules.
5.3 Heap Machine
In this section, we introduce an environment-based abstract machine. Free variables are interpreted as pointers into a heap that store their values. But first, some auxiliary definitions.
Definition 11 (Closure).
A closure is a pair consisting of a program and pointer . The pointer binds the free variables in the program to the values in the heap.
Definition 12 (Heap).
A heap is defined as a list of heap cells where each cell consists of a closure and an additional pointer . The pointer points to the previous cell in the heap, providing a linked list representation of the heap.
Let be list concatenation, and be the standard length function for lists.
Definition 13 (Put and Lookup).
In lookup, let .
The states of the heap machine are triplets consisting of a task stack, a value stack and a heap. We store values in the heap, and replace variables with pointers instead of directly substituting values in-place.
The transition rules for the heap machine are shown in Figure 4. Compared to Section 5.2, there are some minor differences that are not directly related to substitution, but are convenient in the proofs. For example, we spell out the structure for the case, so this rule does not have to use the function.
In our proofs, we write heap machine transitions as , where is a triple representing the current task stack, value stack, and heap. We obtain a new state after applying the transition rules times on the current state, with the size of the biggest intermediate state being . We elide or when irrelevant.
Correspondence between programs and CBPV terms is here relative to an environment. We therefore use the unfolding judgement, written , which takes as inputs a heap , a pointer , a variable bound number , and two CBPV terms and . It returns true when is identical to with all of its free variables replaced by their values in . A representative subset of the unfolding rules are shown in Figure 5. The two variable rules are the interesting ones. The first variable rule unfolds a bound variable to itself. The second variable rule (at the bottom) unfolds free variables to their value on the heap.
We define a heap-aware correspondence using the unfolding function as follows:
Definition 14 (Closure-Term Correspondence with Heap).
: For any closure with heap and CBPV term , is the corresponding closure for (written as ) if and only if there exists a CBPV term such that and .
We prove in HOL4 that the heap machine can simulate CBPV with constant overhead in time:
Lemma 15 (Heap Machine Time Simulation).
If then there exists such that , where and and .
Proof.
By rule induction on the big-step semantics of CBPV. The space cost is unrelated to that of the CBPV reduction. Instead, the size of the state is bounded by the size of the original CBPV term, and the number of steps:
Lemma 16 (Heap Machine Space Simulation).
If and then .
Proof.
The proof proceeds by showing each stack’s length and that all elements in each stack are bounded by the size of the original term and the number of transitions taken .
6 CBPV is Reasonable for Both Time and Space
In this section, we use the results from Section 5 to prove that CBPV is reasonable. We achieve this by providing two simulations between CBPV and Turing machines, as elaborated in Figure 6.
Section 6.1 describes how Turing machines can simulate CBPV with polynomial time overhead and constant factor space overhead, fulfilling Theorem 1 in Section 2. Note that this simulation goes through the abstract machines we implemented and formalised in Section 5.
Section 6.2 describes how CBPV can reasonably simulate WCBV. We adapt the result that WCBV can reasonably simulate Turing machines from existing literature [11]. Together, we have that CBPV can simulate Turing machines with polynomial time overhead and constant factor space overhead, fulfilling Theorem 2 in Section 2.
6.1 Turing Machines Simulating CBPV
In this section we show that it is always possible to construct a Turing machine that simulates CBPV with polynomially bounded time overhead and constant factor space overhead. The results from Section 5, specifically, Lemmas 9, 10, 15, and 16, will be used here.
Our proof is very similar to a proof from the literature [11], where similar heap and substitution machines are interleaved to obtain a simulation of WCBV rather than CBPV. Their proof relies on formalised results similar to our formalised results, and proves that the interleaving strategy always obeys the required time and space bounds. We demonstrate that their argument extends to the more general case of CBPV. While our abstract machines are much more involved, they have similar time and space bounds, which simplifies adaptation.
We need to construct Turing machines and that simulate the respective abstract machines. We must then prove that one can always construct a Turing machine that interleaves and such that they always obey the required bounds.
The substitution-based Turing machine is constructed by iterating over smaller Turing machines each simulating an individual transition rule from Figure 3. Similarly, the heap-based Turing machine is constructed by iterating over Turing machines simulating the rules of Figure 4. In addition to the original CBPV term , each of these machines takes as input a number of steps that they are meant to simulate. The takes an additional input and aborts if the amount of space used is larger than . The encoding of the machine transition rules in Turing machines is straightforward, where we use 13 symbols to represent the 13 constructors(tokens) in the substitution machine. Similarly, we use 12 symbols to represent the 12 constructors(tokens) in the heap machine.
The algorithm then constructs by interleaving the above two machines, and . Provided an input which has a normal form , the algorithm starts by applying over (the program equivalent of) to reduce it. If a size explosion occurs during this reduction, execution then switches to use before the explosion happens. In this case, the heap-based strategy is guaranteed not to encounter the pointer explosion problem [11]. That is because the terms that cause size explosions result in a space cost of , which easily accommodates the space cost for pointer storage in the heap machine. This algorithm guarantees termination and reasonable time and space overhead.
Now let’s construct the Turing machines. In the following theorems, we write for the number of transition steps and for size of the biggest intermediate term.
We first consider the substitution machine. takes as inputs a term , two numbers and . is the term to be reduced, represents the number of transition steps to perform, and represents the space threshold over which the machine should abort. We show that this machine must satisfy one of the following three conditions: (1) it returns a desired value within steps; (2) it reaches the space bound and halts; (3) it finishes reductions and halts (within both space and time bounds). This is formally stated below as Theorem 17.
Theorem 17.
There exists a Turing machine that takes as inputs and a term . It halts in time ( poly(min ())) and space (min () + log + log ) while one of the following statements holds:
-
The machine outputs a term , then has normal form and and .
-
The machine halts in a state named space bound not reached and holds.
-
The machine halts in a state named space bound reached and holds.
Proof.
We can construct a Turing machine by looping Turing machines that implement the individual steps of the abstract substitution machine. We add an extra rule where this machine has to halt if it were to reach a state with size larger than . Note that the extra rule requires to halt even if it is in the middle of execution, in order to avoid the size explosion problem. With an initialisation function that converts from a -term into a program , we now have the desired Turing machine .
The time and space cost from the substitution machine mostly carry over directly, but the extraction functions cannot be implemented in constant time. For instance, takes time and space .
From Lemma 10, we know that if then there exists such that , where and and . Thus the size of all intermediate states and the overall space consumption lie within .
From Lemma 9, we know that if , then there exists such that where and and . Thus there must exist a that is large enough to simulate the reduction while still lying within the bound .
The next step is to construct the heap-based Turing machine :
Theorem 18.
There exists a Turing machine that, given a number and a closed term , halts in time (poly(,)) and space ( poly()). If has a normal form and , it computes a heap and a closure such that . Otherwise, it halts in a distinguished final state (denoting “failure”).
Proof.
We can implement the abstract substitution machine from Section 5.3 by looping Turing machines that implement the individual steps of the abstract machine.
Time and space cost of the functions is as in Theorem 17. We also have to consider the function. iterates through the heap for indices using the heap headers ( in this case) as pointers, resulting in at most time cost.
Thus each abstract step can be implemented in time and space. The space consumption of all involved operations in Figure 4 is bounded by their input or output. Using Lemma 16, the size of all intermediate can be bound by k and to derive the claimed resource bounds. The successful computation of and for large enough follows with Lemma 15.
Before constructing , we need a lemma to say that unfolding only changes de Bruijn indices starting at k. In particular, closed terms are invariant under unfolding.
Lemma 19.
If is bounded by , then .
Proof.
Induction on .
We now combine everything together to form our final theorem.
Theorem 20.
There is a Turing machine that, given a closed term s that has a normal form t, computes a heap H and a closure g such that g t in time (poly(, )) and space ().
Proof.
By using the interleaving algorithm (Algorithm 1) adapted from WCBV [11].
Let p be the polynomial such that the machine from Theorem 18 runs in space ().
-
1.
Initialise (in binary)
-
2.
Compute (in binary)
-
3.
Run on , and .
-
(a)
If computes the normal form , output () and an empty heap [ ] and halt.
-
(b)
If halts with space bound not reached, set and go to 2
-
(c)
If halts with space bound reached, continue at 4.
-
(a)
-
4.
Run on and .
-
(a)
If this computed a closure and a heap representing , output and and halt.
-
(b)
Otherwise, set and go to 2.
-
(a)
There are four things to prove about the algorithm. We will go through them one by one.
Halting states.
has only two halting states: when returns (state 3(a) in Algorithm 1), and when returns (state 4(a)). In both cases, returns a closure-heap pair representing the normal form of . In the first case, Theorem 17 shows that will return a normal form of and Lemma 19 shows that the closure-heap pair we constructed in state 3(a) indeed represents t. The second case is immediate Theorem 18.
Termination.
The machine will terminate for terminating terms and diverge on non-terminating CBPV terms. For the terminating case, we need to show two things: (1). for all , each iteration eventually finishes and goes to the next iteration; (2). there exists a such that the machine halts and returns a closure-heap pair. We consider (1) first, and fix . Time cost in step 1 is constant. Binary computation in Turing machines have polynomial cost, thus the time cost in step 2 is . Using Theorem 17, step 3 takes time
If Step 4 is executed, this takes time by Theorem 18. Since each of the four steps has at most time complexity , one iteration has time cost , which suffices for (1). For (2), consider , which is larger than the two values required in Theorem 17 and Theorem 18. By Theorem 17, the machine does halt during Step 3, unless . In the latter case, 4 is tried. Then, by Theorem 18, as is large enough, we have that indeed halts with a closure-heap pair.
Time Complexity.
We have proved the time cost for each iteration, so we just need to sum up all the iterations for the overall time complexity for :
Space Complexity.
We first analyse the space cost for one iteration with an arbitrary . Step 1 is constant. Step 2 takes space since the computation is in binary. By Theorem 17, Step 3 takes space . If step 3(c) reaches the space bound (), step 4 is tried. Together with Theorem 18 and definition of , the space cost for step 4 is .
Thus we have the space cost of one iteration:
The space cost for all iterations is as follows, where the last equation is by Lemma 21:
By combining our formalisation with results above, we obtain Theorem 2.
For terms with it is crucial that the machine tracks the step number in binary, because it would need space otherwise. This suffices because of Lemma 21:
Lemma 21.
Proof.
As the vocabulary is finite, there are at most exponentially many terms for a given size. A reduction from cannot visit the same term twice since reduction is deterministic. is the biggest intermediate term, which means that all the terms in the reduction for will be smaller than . This implies that will be at most equal to the total number of terms smaller than . Formally: for a constant c.
To see that the number of terms smaller than a given size is at most exponential, note that by Lemma 6. Because is injective we have , which is . Finally, follows by induction on . The 5 is because there are four different symbols a program can start with, and variables indices use a fifth symbol.
6.2 CBPV Simulating WCBV
In this section, we prove that CBPV can simulate Turing machines with reasonable time and space overhead. We achieve this by using WCBV as an intermediate model. There is existing work showing WCBV can simulate Turing machines with reasonable time and space overhead [11]. Thus what remains to be shown in this section is a reasonable simulation of WCBV using CBPV. With prior work, this suffices to prove Theorem 2.
Let denote the set of WCBV -terms constructed from the following grammar:
WCBV does not allow reduction under . Time and space cost semantics are as in [11]:
The compilation function is then defined as follows:
We prove that CBPV can simulate WCBV with constant overheads, by a routine induction:
Theorem 22.
For each closed WCBV term , we have:
-
1.
If , then there exists such that and ; and
-
2.
If , then there exists such that and .
Note that the standard translation uses twice instead of once, like this:
Some de Bruijn arithmetic is needed to account for the extra binder in the case. Environments are (partial) functions from to . We define lifting operators as follows:
However, it turns out that has linear space overhead, because there exists terms such that , as shown by the following example. Consider a term consisting of right-associated applications, followed by occurrences of the variable . For example, we’d have the following, where denotes the identity function :
We have . But if we consider , the occurrences of in become occurrences of , and hence .
This technicality arises because de Bruijn indices count towards term size. We must count like so because numbers are not representable in constant space on Turing machines.
Fortunately, the problematic additional bindings introduced by applications are vacuous over the operand. Translating CBPV to WCBV requires introducing intermediary bindings, and we cannot solve the issue by shuffling arguments: it is necessary for either the operator or operand of an application to be in the scope of a vacuous binding. Based on this observation, we conjecture that without (or products), CBPV is not reasonable for space.
6.2.1 Do we need to go to Turing machines?
Since WCBV is known to be reasonable, the reader may wonder if we must go all the way to Turing machines to prove Theorem 2. Wouldn’t going to WCBV be simpler? This turns out to be straightforward for time cost, but unfortunately the natural encoding of CBPV in WCBV has linear space overhead (cf. Section 6.2). Consider this compilation function:
We flatten the distinction between values and computations, and to suspend computations we use the one mechanism on offer: -abstraction. We have proved that this compilation strategy is reasonable for time cost. Unfortunately, it does not yield a reasonable space cost model. To see why, consider the following variation on the example from the previous section.
That is, term contains mentions of under layers of thunks. We have . But when we consider , the occurrences of in become occurrences of , and hence .
Clearly a reasonable encoding in this direction is impossible: the detour via Turing machines would yield one. But the choice of encoding function would not be obvious.
7 Conclusion and Future Work
In this paper, we establish the first time and space cost models for the CBPV -calculus and formally verify that CBPV relates to intermediate abstract machines. These intermediate machines are interleaved to maintain the desired time and space bounds in relation to Turing machines by extending known results about weak call-by-value [11, 12]. Together, this gives the first proof that CBPV is a reasonable model of computation. Hence, CBPV can serve as a basis for reasoning about the computational complexity of functional programs.
In future work we plan to investigate cost models for extensions to CBPV that support call-by-need evaluation. Moreover, it is unclear how the Bang calculus [9] relates to CBPV in terms of time and space cost, and whether the Bang calculus is reasonable. It would also be interesting to consider sublinear complexity classes. Finally, it would be interesting to extend our work into cost models for -calculus variants with different evaluation strategies, thus laying the foundation for a unifying approach of complexity analysis for the -calculus.
References
- [1] Beniamino Accattoli. (in)efficiency and reasonable cost models. In Sandra Alves and Renata Wasserman, editors, 12th Workshop on Logical and Semantic Frameworks, with Applications, LSFA 2017, Brasília, Brazil, September 23-24, 2017, volume 338 of Electronic Notes in Theoretical Computer Science, pages 23–43. Elsevier, 2017. doi:10.1016/j.entcs.2018.10.003.
- [2] Beniamino Accattoli and Ugo dal Lago. (leftmost-outermost) beta reduction is invariant, indeed. Log. Methods Comput. Sci., 12(1), 2016. doi:10.2168/LMCS-12(1:4)2016.
- [3] Beniamino Accattoli, Ugo Dal Lago, and Gabriele Vanoni. Reasonable space for the -calculus, logarithmically. In Christel Baier and Dana Fisman, editors, LICS ’22: 37th Annual ACM/IEEE Symposium on Logic in Computer Science, Haifa, Israel, August 2 - 5, 2022, pages 47:1–47:13. ACM, 2022. doi:10.1145/3531130.3533362.
- [4] Zhuo Chen. cbpv-reasonable-hol, June 2025. URL: https://github.com/ZhuoZoeyChen/cbpv-reasonable-HOL.
- [5] Zhuo Zoey Chen, Johannes Åman Pohjola, and Christine Rizkallah. cbpv-reasonable-HOL. Software, swhId: swh:1:dir:df18377e9fa5e35255f2687ad66ddbc2f010b934 (visited on 2025-09-11). URL: https://github.com/ZhuoZoeyChen/cbpv-reasonable-HOL/, doi:10.4230/artifacts.24718.
- [6] Jules Chouquet and Christine Tasson. Taylor expansion for call-by-push-value. In Maribel Fernández and Anca Muscholl, editors, 28th EACSL Annual Conference on Computer Science Logic, CSL 2020, January 13-16, 2020, Barcelona, Spain, volume 152 of LIPIcs, pages 16:1–16:16. Schloss Dagstuhl – Leibniz-Zentrum für Informatik, 2020. doi:10.4230/LIPICS.CSL.2020.16.
- [7] Alonzo Church. A set of postulates for the foundation of logic. Annals of Mathematics, 33(2):346–366, 1932. URL: http://www.jstor.org/stable/1968337.
- [8] Ugo dal Lago and Simone Martini. The weak lambda calculus as a reasonable machine. Theor. Comput. Sci., 398(1-3):32–50, 2008. doi:10.1016/j.tcs.2008.01.044.
- [9] Thomas Ehrhard and Giulio Guerrieri. The bang calculus: an untyped lambda-calculus generalizing call-by-name and call-by-value. In James Cheney and Germán Vidal, editors, Proceedings of the 18th International Symposium on Principles and Practice of Declarative Programming, Edinburgh, United Kingdom, September 5-7, 2016, pages 174–187. ACM, 2016. doi:10.1145/2967973.2968608.
- [10] Thomas Ehrhard and Christine Tasson. Probabilistic call by push value. CoRR, abs/1607.04690, 2016. arXiv:1607.04690.
- [11] Yannick Forster, Fabian Kunze, and Marc Roth. The weak call-by-value -calculus is reasonable for both time and space. Proc. ACM Program. Lang., 4(POPL):27:1–27:23, 2020. doi:10.1145/3371095.
- [12] Yannick Forster, Fabian Kunze, Gert Smolka, and Maximilian Wuttke. A mechanised proof of the time invariance thesis for the weak call-by-value -calculus. In Liron Cohen and Cezary Kaliszyk, editors, 12th International Conference on Interactive Theorem Proving, ITP 2021, June 29 to July 1, 2021, Rome, Italy (Virtual Conference), volume 193 of LIPIcs, pages 19:1–19:20. Schloss Dagstuhl – Leibniz-Zentrum für Informatik, 2021. doi:10.4230/LIPIcs.ITP.2021.19.
- [13] Yannick Forster, Steven Schäfer, Simon Spies, and Kathrin Stark. Call-by-push-value in coq: Operational, equational, and denotational theory. In Assia Mahboubi and Magnus O. Myreen, editors, Proceedings of the 8th ACM SIGPLAN International Conference on Certified Programs and Proofs, CPP 2019, Cascais, Portugal, January 14-15, 2019, pages 118–131. ACM, 2019. doi:10.1145/3293880.3294097.
- [14] Dmitri Garbuzov, William Mansky, Christine Rizkallah, and Steve Zdancewic. Structural operational semantics for control flow graph machines. CoRR, abs/1805.05400, 2018. arXiv:1805.05400.
- [15] G. A. Kavvos, Edward Morehouse, Daniel R. Licata, and Norman Danner. Recurrence extraction for functional programs through call-by-push-value. Proc. ACM Program. Lang., 4(POPL):15:1–15:31, 2020. doi:10.1145/3371083.
- [16] Delia Kesner and Andrés Viso. The power of tightness for call-by-push-value. CoRR, abs/2105.00564, 2021. arXiv:2105.00564.
- [17] Fabian Kunze, Gert Smolka, and Yannick Forster. Formal small-step verification of a call-by-value lambda calculus machine. In Sukyoung Ryu, editor, Programming Languages and Systems - 16th Asian Symposium, APLAS 2018, Wellington, New Zealand, December 2-6, 2018, Proceedings, volume 11275 of Lecture Notes in Computer Science, pages 264–283. Springer, 2018. doi:10.1007/978-3-030-02768-1_15.
- [18] Julia L. Lawall and Harry G. Mairson. Optimality and inefficiency: What isn’t a cost model of the lambda calculus? In Robert Harper and Richard L. Wexelblat, editors, Proceedings of the 1996 ACM SIGPLAN International Conference on Functional Programming, ICFP 1996, Philadelphia, Pennsylvania, USA, May 24-26, 1996, pages 92–101. ACM, 1996. doi:10.1145/232627.232639.
- [19] Paul Blain Levy. Call-by-push-value: A subsuming paradigm. In Jean-Yves Girard, editor, Typed Lambda Calculi and Applications, 4th International Conference, TLCA’99, L’Aquila, Italy, April 7-9, 1999, Proceedings, volume 1581 of Lecture Notes in Computer Science, pages 228–242. Springer, 1999. doi:10.1007/3-540-48959-2_17.
- [20] Paul Blain Levy. Call-by-Push-Value. PhD thesis, Queen Mary University of London, UK, 2001. URL: https://ethos.bl.uk/OrderDetails.do?uin=uk.bl.ethos.369233.
- [21] Paul Blain Levy. Adjunction models for call-by-push-value with stacks. In Richard Blute and Peter Selinger, editors, Category Theory and Computer Science, CTCS 2002, Ottawa, Canada, August 15-17, 2002, volume 69 of Electronic Notes in Theoretical Computer Science, pages 248–271. Elsevier, 2002. doi:10.1016/S1571-0661(04)80568-1.
- [22] Dylan McDermott and Alan Mycroft. Extended call-by-push-value: Reasoning about effectful programs and evaluation order. In Luís Caires, editor, Programming Languages and Systems - 28th European Symposium on Programming, ESOP 2019, Held as Part of the European Joint Conferences on Theory and Practice of Software, ETAPS 2019, Prague, Czech Republic, April 6-11, 2019, Proceedings, volume 11423 of Lecture Notes in Computer Science, pages 235–262. Springer, 2019. doi:10.1007/978-3-030-17184-1_9.
- [23] Robin Milner, Mads Tofte, and Robert Harper. Definition of standard ML. MIT Press, 1990.
- [24] Christine Rizkallah, Dmitri Garbuzov, and Steve Zdancewic. A formal equational theory for call-by-push-value. In Jeremy Avigad and Assia Mahboubi, editors, Interactive Theorem Proving - 9th International Conference, ITP 2018, Held as Part of the Federated Logic Conference, FloC 2018, Oxford, UK, July 9-12, 2018, Proceedings, volume 10895 of Lecture Notes in Computer Science, pages 523–541. Springer, 2018. doi:10.1007/978-3-319-94821-8_31.
- [25] Konrad Slind and Michael Norrish. A brief overview of HOL4. In Otmane Aït Mohamed, César A. Muñoz, and Sofiène Tahar, editors, Theorem Proving in Higher Order Logics, 21st International Conference, TPHOLs 2008, Montreal, Canada, August 18-21, 2008. Proceedings, volume 5170 of Lecture Notes in Computer Science, pages 28–32. Springer, 2008. doi:10.1007/978-3-540-71067-7_6.
- [26] Cees F. Slot and Peter van Emde Boas. On tape versus core; an application of space efficient perfect hash functions to the invariance of space. In Richard A. DeMillo, editor, Proceedings of the 16th Annual ACM Symposium on Theory of Computing, April 30 - May 2, 1984, Washington, DC, USA, pages 391–400. ACM, 1984. doi:10.1145/800057.808705.
- [27] Cassia Torczon, Emmanuel Suárez Acevedo, Shubh Agrawal, Joey Velez-Ginorio, and Stephanie Weirich. Effects and coeffects in call-by-push-value (extended version). CoRR, abs/2311.11795, 2023. doi:10.48550/arXiv.2311.11795.
- [28] Peter van Emde Boas. Chapter 1 - machine models and simulations. In Jan Van Leeuwen, editor, Algorithms and Complexity, Handbook of Theoretical Computer Science, pages 1–66. Elsevier, Amsterdam, 1990. doi:10.1016/B978-0-444-88071-0.50006-0.
