Tags

dual calculus

Wadler's dual calculus is a term assignment system for Gentzen's system LJ; i.e., the classical sequent calculus.

1. syntax

The notation makes use of a pair of mnemonic conventions:

  • unary term formers are written postfix, while unary coterm formers are written prefix;
  • angle brackets enclose terms, square brackets enclose coterms, and parentheses enclose statements.

Here is some intuition for these constructs.

  • forms a pair of two terms and .
  • takes a continuation and essentially precomposes the first projection with it. In other words, turns from a continuation that expects a value of type into a continuation that expects a value of type . is similar.
  • injects the term into a sum on the left; injects the term into a sum on the right.
  • performs case analysis on a sum value, executing in case it is a left value and in case it is a right value.
  • converts a coterm into a value. Specifically, a coterm that expects a value of type becomes a continuation of type .
  • converts a term into a covalue. Specifically, a term becomes a covalue that, upon receiving a continuation value , passes the result of evaluating to .
  • abstracts over the covariable , converting the statement into a term that yields whatever value is passed to . Likewise abstracts over the variable , converting the statement into a coterm that awaits a value for .
  • Function abstraction has the usual interpretation. Function application works a little differently, though.

2. types

There are three kinds of type judgments: one for terms, one for coterms, and one for commands.

All judgments involve two lists of assumptions, one on each side of a turnstile , just as in the sequent calculus. On the left, means that the variable stands for a value of type . On the right, means that the covariable stands for a covalue of type (i.e., a computational context with a hole of type ).

For terms, means that, given the assumptions in and , the term has type . Computationally, it means that, if each variable in is assigned a value of appropriate type, then will either evaluate to a value of type or pass to a covariable in a value of appropriate type.

For coterms, means that, given the assumptions in and , the coterm has type . Computationally, it means that, if each variable in is assigned a value of appropriate type and is passed a value of type , then it will pass to some covariable in a value of appropriate type.

It may seem odd that judgments are written on the right for terms and on the left for coterms. However, they correspond respectively to right and left rules in the sequent calculus, so the choice makes sense. Also observe that the computational interpretation has a disjunctive flavor for term judgments and a conjunctive flavor for coterm judgments.

Finally, for statements, means that, given the assumptions in and , the statement is well-typed. Computationally, it means that, if each variable in is assigned a value of appropriate type, then will pass to some covariable in a value of appropriate type.

2.1. products

These correspond to the rules for conjunction in sequent calculus.

2.2. sums

These correspond to the rules for disjunction in sequent calculus.

2.3. functions

2.4. negations

Syntactically, these convert between terms and coterms. Logically, they correspond to the rules for negation.

  • converts a coterm into a term: a coterm that expects a value of type becomes a term of type .
  • converts a term into a coterm. Specifically, a term becomes a covalue that, upon receiving a continuation value , passes the result of evaluating to .

2.5. abstractions

Syntactically, these convert center sequents to right or left sequents. Standard sequent calculi do not distinguish classes of sequents in this way, so these rules do not correspond to any standard logical rules.

2.6. statements

Logically, this corresponds to the cut rule.

3. elimination rules

Can we recover elimination rules from the left rules?

Yes, we can. Every left rule is very much like the contrapositive of an elimination rule. An elimination rule for says something like “give me a value of type and I will extract some data from it.” A left rule for says something like “give me a place to put some data from a value of type and I will give you a place to put a value of type .” To recover an elimination rule, we simply need to feed in a value of type and tell the left rule to put the data right here. That is, if , we write , where is an expression that applies a left rule, using as the final continuation.

3.1. products

3.2. sums

3.3. functions

4. other types

4.1. cofunctions?

It's worth wondering whether we can dream up a sensible dual for functions.

Let's begin by just thinking about logic. The de Morgan dual of is , also written . (The latter notation can be justified by the equivalence .) We can derive its right rule from the left rule for implication.

And likewise, its left rule from the right rule for implication.

Using term names, the right rule becomes

and the left rule becomes

From the right rule, it is clear that a “cofunction” is fundamentally just a pair of a value and a continuation . The computational interpretation of the left rule is that, if we have a way to produce a given an , then a cofunction gives us both a and something to do with the resulting .

Author: Nicholas Coltharp (mail@heraplem.xyz)

Last modified: 2026-08-08 Sat 00:57

Emacs 30.2 (Org mode 9.7.11)

Validate