Many logic systems admit a weakening principle: a
derived conclusion continues to hold when more assumptions are
added. Strengthening is the opposite: proving that the established
conclusion holds given fewer assumptions. Strengthening certainly
is not generally valid and has to be proven case-by-case. It seems
strengthening is often needed when proving meta-theoretical
properties such as totality of non-surjective endomorphisms of
higher-order terms.

The article on Twelf Wiki <http://twelf.plparty.org/wiki/Strengthening>
shows an example of the need for strengthening and describes one
solution, which relies on defining term equality. In this article
we demonstrate simpler examples requiring strengthening, and two
surprisingly trivial solutions. Quite literally, one solution deals
with the problem head-on, whereas the second one avoids the problem
in a round-about way. The examples are inspired by staging calculi.
At the end we describe the real development, which gives perhaps
the first formal proof of type preservation of primitive reductions
in an expressive staged calculus with escapes, run and cross-staged
persistence. The type-preservation proof used both of our solutions
and required two strengthening lemmas. Throughout we use Twelf –
properly: we use the higher-order abstract syntax (HOAS) for
higher-order terms, without ever resorting to concrete syntax for
“variables”. The complete code is available at <http://okmij.org/ftp/Computation/staging/>
.

The simplest example requiring strengthening

Perhaps the simplest example to illustrate the need of
strengthening is based on lambda-calculus with terms marked by
either 1 or 0. The challenge is to implement a function that
converts terms marked by 1 into those marked by 0 – and show its
totality.

The clause cp1-a inductively handles applications.
To transform an abstraction, we assume a term x marked
with 1, a term x' marked with 0, and assume that
x' is the result of transforming x, see
cp1 x x'. Under those assumptions, we transform the
body of the abstraction, cp1 (E1 x) (E1' x'). The
notation (E1' x') means that E1' is a
higher-order term applied to x'. That is,
E1' is of the type exp 0 -> exp 0. The
block declaration cp1-l-bl lists our set of
assumptions; the regular worlds declaration asserts that
cp1 is performed given no assumptions, or one set
assumption cp1-l-bl, or two sets of such assumptions
(with the different x and x' across the
sets), etc.

Our transformation procedure is obviously total: we can take any
1-marked term, and, in finite time, always deliver the
corresponding 0-marked term. We wish to state this formally, hence
the %total assertion. Twelf verifies it first by
checking that the transformation is terminating. It then checks
that all pattern-matching is exhaustive: we have not missed a case.
Alas, the totality check fails and Twelf reports an error:

In the clause cp1-l, we have introduced three
assumptions: x, x' and cp1 x
x'. By writing (E1' x') we asked the Twelf
system to “factor out” the dependence on x'.
Implicitly we stated that the result of transforming (E1
x) depends only on x' but not on x
or cp1 x x' (more formally, the independence is seen
from the fact E1' is used outside of the scope of
x introduced via the universal quantification
{x} in cp1-l). Twelf can see that the
assumption cp1 x x' cannot possibly enter the set of
terms because the definition of the type family exp
(with constructors a and l) shows that no
term can contain anything of the type cp1. But terms
may occur in terms, and so the result of transforming the body of
the abstraction generally depends on both x and
x'. We have not handled that general case, and so our
transformation is not total.

Twelf’s complaint is quite insightful: (E1 x) is
the body of the abstraction that includes some term x
(“the variable”). We transform the body replacing all those
occurrences of x with x' – and so the
result should include only x' but no x.
Thus Twelf demands the proof that we indeed replaced all
those x with x'.

Upon consideration, we can see that the result of transforming
(E1 x) cannot really depend on, or contain,
x. After all, x is an expression marked
by 1 and the result of transforming (E1 x) is an
expression marked by 0. Any sub-expression of a marked expression
is marked with the same mark. Alas, Twelf cannot see this proof by
itself and we have to write it down explicitly. The reason Twelf
cannot see that proof by itself is because Twelf tracks the
dependencies (so-called subordination)
using only the names of the type families (e.g., exp)
but not their parameters (e.g., exp 0 or exp
1).

Astonishingly, the most trivial way of writing this independence
proof works. We state that whenever a term marked by 0 appears to
depend on a term marked by 1, it actually doesn’t. Or,
constructively, we assert the following proposition

strength : (exp 1 -> exp 0) -> exp 0 -> type.
%mode strength +H -E.

For any implication exp 1 -> exp 0, we
can always constructively produce exp 0. Here is the
proof, the detailed procedure of producing that exp 0
term:

The first clause handles the case when E patently
does not contain anything of the type exp 1. The rest
of the clauses do straightforward induction on terms; the last
clause requires hypothetical reasoning to examine the body of the
abstraction, and for that we introduce the assumption
x' of the type exp 0. Perhaps it is
because of that hypothetical reasoning that Twelf cannot see the
strengthening property on its own. We assert that so defined
procedure is total, i.e., it is a constructive proof of the
strength proposition:

The label cp2-l-bl describes the set of assumptions
of the improved cp2 procedure below (in the actual
code, it is defined in a forward declaration). Twelf has verified
the totality of strength, and so we can use it to write the
improved transformation procedure, cp2:

The only difference from cp1 is in the clause
cp2-l: by writing (E1' x x') we state
that the result of transforming the body of the abstraction may
depend not only on x' but also on x. We
build the transformed abstraction under that additional assumption:
([x:exp 1] (l (E1' x))). Using strengthening, we then
prove that (l (E1' x)) does not actually depend on
x. Now the totality assertion succeeds:
cp2 is the total transformation of 1-marked terms.

We introduce a simple staged language, where each expression is
annotated with the numeric stage label A. The language
has three forms of expressions: natural literals, addition, and fix
(i.e., recursive functions).

We introduce a trivial type system with only one type,
int, and the equally simple type-checking relation
of E T:

of : exp A -> tp -> type. %name of Q.
%mode of +E *T.

Please see the code for details. As in the previous section we
write the procedure to downgrade the level of an expression

downgrade : exp (1 N) -> exp N -> type.
%mode downgrade +E1 -E2.

We are not that interested in proving downgrade is total.
Rather, we wish to prove a meta-theorem that downgrade
is type preserving: if the original expression was typed, the
downgraded expression shall be typed too. We state that property as
a constructive proposition:

That is, given any downgradeable expression E1 and
its type derivation of E1 T (the evidence that
E1 is typed), we produce the typing derivation for the
corresponding downgraded expression E2. The most
interesting case is the following:

Here, dn-f PEH of the type downgrade (fix E1)
(fix E2) is the derivation of downgrading (fix
E1) into (fix E2). We assume a term
e of the type exp (1 A), and further
assume it is typed (the assumption pt:of e int).
Likewise we assume a typed term e' that is the result
of downgrading e. Finally, we assume that the
downgrading from e to e' was type
preserving. Under those assumptions, we obtain the type derivation
of the body of the downgraded fix, by inductively invoking dn-pres.
The resulting type derivation (PTH' e pt e' pt')
generally depends not only on the assumption e' and
its typeability pt' – but also on e and
pt, which are in scope and could in principle occur in
type derivations. We must thus prove that we can remove the latter
dependency. Again, the formal statement of that proposition is
surprisingly simple:

We assert that the typing derivation of E T for an
expression E at the level N cannot depend
on any N+1-level expression e and the
typing derivation of the latter. Our proof is again constructive:
from the corresponding implication we produce its conclusion
without assuming the hypotheses. The complete code has all
details.

Other examples

The need for strengthening does occur (although not frequently)
in other circumstances. Here are the example from Twelf
distribution. One is “Representation of Mini-ML expressions in
Mini-ML*” by David Swasey, file
exercises/opt-eval/opt-rep1.elf. It defines a
transformation from one higher-order language to another. Proving
meta-theoretical properties of that translation (totality, type
preservation, etc) requires strengthening.

The second, indirect solution

The second solution to strengthening is, too, trivial, albeit
round-about. We use the same problem as in Section 1: in
lambda-calculus whose terms are marked with 0 or 1, implement a
function that converts terms marked by 1 into those marked by 0 –
and show its totality.

Rather than transforming exp 1 to exp
0 directly, we introduce terms expi M
isomorphic to exp M, turn exp 1 to
expi 1 and then transform expi 1 to
exp 0. The advantage is that terms exp M
cannot appear in expi M and vice versa, so exp
M cannot depend on assumptions of the type {x:expi
M} and vice versa. We avoid strengthening altogether.

that are clearly isomorphic to the terms exp M of
the original calculus. We can state the isomorphism formally;
however, we only need one direction of it: given any term exp
M, we can always obtain the corresponding expi
M:

Now Twelf verifies the totality assertion without any complaints
that E1' could depend (that is, include) the
assumption e, which is also present in the LF context.
Twelf now sees that E1' cannot include e.
Compared to Section 1, converting an expression of the type
exp M gives us the term of the type expi
M. The latter terms can only be constructed by
l2 and a2; neither constructor can take
any argument of the type exp M or contain exp
M elsewhere. Strengthening is no longer needed.

The label-changing transformation now takes expi 1
rather than exp 1 as the source a term:

Again, Twelf accepts the totality assertion without complaint
because clearly no term of the type expi M may appear
in the term exp M – in fact, expi was
not even defined when exp was introduced. Thus
(E1' x') cannot depend on x.

The desired transformation now includes two steps: transforming
the source expression into the isomorphic form, and changing the
mark of the latter. Albeit indirect, the solution avoids
strengthening altogether.

The file includes (maybe the first) formal proof that any
non-value term can be decomposed into a pre-value and the context.
This is quite challenging given that the calculus supports the
evaluation under lambda and so the context can cross the arbitrary
number of dependent binders: variable binders include
classifiers that must be bound, too, at that point.

In our staged calculus, all terms are marked by their stage,
present and future. This is quite like the examples in the earlier
Sections. There is also an operation to demote a term, which takes
a future-stage-marked term and changes its mark so the term can be
evaluated at the present stage. Demotion is how a future-stage
computation can be run. Demotion rebuilds a term as it
traverses it, changing the marks along the way. The only special
case is handling a cross-staged persistent (CSP) value. The latter
is a present-stage expression that was “lifted” to the future
stage, i.e., was encapsulated unevaluated. The demotion operation
merely removes the encapsulation, splicing CSP into the demoted
code.

The type-preservation proof is at the end of the development.
The most complex part is proving that demotion is type preserving,
in particular, that demoting an abstraction (l [x:exp (1q
AL)] Body) from the future stage (marked by (1q
AL)) to the present, marked as qt, stage
yielding (l [x':exp qt] Body') is type preserving. As
in the simpler examples earlier, the proof proceeds by introducing
assumptions {x:exp (1q AL)}, {x':exp qt}
and that x' is the result of demoting x.
The challenge is to prove that Body' does not actually
depend on x. That is no longer as simple as before: a
future-stage expression exp (1q AL) could actually
occur in the demoted expression – because of CSP. For example,
consider the following future-stage term

(l [x:exp (1q AL)] (csp (AL > x)))

where AL > x is future-stage-x
marked by classifier AL (in the PEPM08 paper, we write
(l [x^AL] %(<x>^AL)). An attempt to run such
future-stage computations does not type in MetaOCaml; accordingly,
the lambda-a1v calculus rejects such expressions as
mis-typed, due to a special typing rule of CSP. Our preservation
proof must take into account that the demoted expression is typed
and so possible CSPs are restricted in form. Only then
strengthening can be proven.

In our proof, we had to use both approaches to proving
strengthening described in this article. We had to prove a direct
strengthening lemma

asserting that the typing of a present-stage expression
(of (E:exp qt) T) cannot depend on a future-stage
expression exp (1q AL) and the latter’s typing
derivation (of (_:exp (1q AL)) T) – provided
that E is the result of a demotion. We also use the
indirect approach and introduce a CSP restriction predicate
csp-ok1 isomorphic to the predicate
csp-ok. The latter may occur in typing derivations but
the former may not. Finally, we had to prove the strengthening
lemma for csp-ok1.