Dependently Typed Higher-Order Logic
by
Cezary Kaliszyk,
Daniel Ranalter,
Geoff Sutcliffe.
Dependently typed higher-order logic (DHOL) is a extension of Church's higher-order logic (HOL)
introduced by Rothgang et al.
[RRB23].
It takes the widely supported HOL and equips it with dependent
types, i.e., types that take term arguments. As such, it is a classical and extensional type
theory, as opposed to the theory used in Rocq, Lean or others which rely on an intensional type
theory. Notable exceptions to this trend are PVS and F*.
While the extensionality of DHOL comes at the cost of making type checking an undecidable
problem in general, the gain is also significant: Having judgmental and provable equality
coincide is much closer to how mathematics is usually done in the context of Automated Theorem
Proving.
Furthermore, the cost - which might seem steep at first glance - is mitigated by the ever
increasing performance of ATP systems and the fact that in many cases the proof obligations
resulting from type checking are simpler than the original conjecture.
The inclusion of dependent types into the formalism allows the elegant definition of data
structures like lists with fixed length, sets of a fixed finite size and others. Having
constraints encoded on the level of types removes the need for lengthy and error prone guards
in programming, and encodes additional, useful information for theorem proving.
Types in DHOL are either fully applied base types, dependent function types, or classical
booleans.
A remark about the binary connectives: Due to type checking, binary connectives like AND and OR
are no longer commutative. Consider as an example the statement
a =A b ⇒ f a =B(a) f b.
The well-formedness of the right-hand side requires the left hand side as premise, which breaks
commutativity for the boolean connectives defined with ⇒. While apparently disruptive, it is
common practice to sacrifice commutativity for, e.g., short-circuit evaluation of boolean terms
in programming languages.
Translation of DHOL
In order to take advantage of the proving power already available for regular HOL, Rothgang et
al. define a dependency-erasure and thereby a translation from DHOL into regular HOL. They also
prove that this translation is sound and complete for well-typed DHOL problems. Due to this
result, and the implementation of the translation in the preprocessor of the Leo-III theorem
prover, there existed reasoning support for DHOL, even before native DHOL reasoning was
implemented into Lash by Niederhauser et al.
[NBK24].
Information lost due to the erasure of term dependencies is captured in Partial Equivalence
Relations (PERs) - symmetric and transitive relations on pairs of terms - with the idea that
the relation is reflexive exactly for those terms that were previously of the same dependent type.
While intuitively one might think unary predicates would be sufficient to specify subtypes for
type guards, a binary equality relation becomes necessary when relating higher-order functions
which are equal when guarded inputs are mapped to equal outputs.
Type Checking
Due to equality reflection, type checking for DHOL is in general undecidable.
Nevertheless, problems need to be well-typed, not least of all because otherwise the translation
outlined previously would not necessarily be sound.
As such, type checking takes up a larger role compared to other logics in the TPTP.
While performing the usual type checking procedure in DHOL, one eventually encounters obligations
of the form
a t1 ... tn ≡ b u1 ... un,
establishing equality of the dependent types a, b of arity n with
t1 ... tn , u1 ... un
being terms of appropriate type.
At this point the type equality judgment is reflected into proving obligations, each establishing
the equality of the corresponding term arguments.
In cases where ti, ui are equal, the obligation can be
dismissed directly by reflectivity.
In general, however, this creates a number of new conjectures that need to be addressed by the
theorem prover.
This sometimes creates interesting situations, where problems need to include axioms not directly
necessary for the conjecture itself, but for type checking the problem.
The common example of fixed length lists is one such instance.
Proving the associativity of append requires the inclusion of the defining equations of append
as well as cons.
To type check the problems it is additionally necessary to include axioms and defining equations
that allow proving the associativity of addition on natural numbers.
The undecidability of type checking does incite finding compromises.
One such compromise is "shallow type checking".
When a problem file is shallowly checked, only the simply typed skeleton of the problem is
considered, i.e., term arguments to types as well as dependent functions are ignored during the
procedure.
Consequently, it collapses to type checking as is done on non-dependently typed problems, and
is decidable.
This form of type checking catches careless mistakes in the formulation of problems and
provides a very basic check of issues usually caught in HOL problems.
Matching the number of arguments to the arity of a function, and egregious type mismatches, are
examples of errors that can be avoided by shallow type checking.
This provides a valuable sanity check for users, especially considering the complexity that
problems in DHOL forms can reach.
Syntax of TPTP Dependently Typed Higher-order Form (DHF)
The syntax of DHF requires next to no change to the already established TPTP language BNF.
The TPTP language already defines the !> binder for types.
This is currently only used for polymorphism e.g.,
cons : !>[A: $tType]: (A > (list @ A) > (list @ A))
might be found as the type statement for a polymorphic cons operation.
However, the TPTP language does not forbid to list terms in the types of such variable lists.
This fact is used to unobtrusively extend TPTP with dependent types.
A dependent type symbol declaration is written with m terms of n types as
a: !>[x1:A1,...,xm:An] : $tType, or alternatively
a: A1 > ... > An > $tType.
Instantiations of such types use the application operator @, applying the terms to the
dependent type: a @ t1 @ ... @ tm.
In polymorphic problems the variable list is prepended with their type variables, which may appear
in the same binder.
An Example Problem in DHF
The following example formalizes the base case of the inductive proof that
append on fixed-length lists is associative.
%------------------------------------------------------------------------------
%----The theory of natural numbers. Well-established and simply typed.
thf(nat_type,type,
nat: $tType ).
thf(zero_type,type,
zero: nat ).
thf(suc_type,type,
suc: nat > nat ).
thf(plus_type,type,
plus: nat > nat > nat ).
thf(ax1,axiom,
! [N: nat] :
( ( plus @ zero @ N ) = N ) ).
%----The second defining equation for 'plus' is not necessary in the base case.
%----The associativity of plus is needed for type checking (and, in fact, only
%----for type checking)
thf(plus_assoc,axiom,
! [M1: nat,M2: nat,M3: nat] :
( ( plus @ M1 @ ( plus @ M2 @ M3 ) )
= ( plus @ ( plus @ M1 @ M2 ) @ M3 ) ) ).
%----A type of arbitrary elements for our list.
thf(elem_type,type,
elem: $tType ).
%----Dependent types: the list type takes a nat typed term and returns a type
thf(list_type,type,
list: nat > $tType ).
%----'nil', the empty list, is specified to have length 0, encoding properties
%----into types that would otherwise need definitions of a length function,
%----additional axioms, etc.
thf(nil_type,type,
nil: list @ zero ).
%----The 'cons' operator is dependently typed, taking a nat corresponding to
%----the length of the input vector. Note that this prevents any conjecture
%----from trying to establish nil' as a result of cons, as this wouldn't
%----type-check.
thf(cons_type,type,
cons:
!>[N: nat] : ( elem > ( list @ N ) > ( list @ ( suc @ N ) ) ) ).
%----'app' is also dependent, incorporating reasoning about plus into the type
%----checking procedure.
thf(app_type,type,
app:
!>[N: nat,M: nat] :
( ( list @ N ) > ( list @ M ) > ( list @ ( plus @ N @ M ) ) ) ).
%----First (and for this conjecture, the only) defining equation of 'app'
thf(ax3,axiom,
! [N: nat,X: list @ N] :
( ( app @ zero @ N @ nil @ X ) = X ) ).
%----The conjecture: The base case of the induction proof. Note that this is
%----part of a larger problem, broken up to make it easier.
thf(list_app_assoc_base,conjecture,
! [M2: nat,L2: list @ M2,M3: nat,L3: list @ M3] :
( ( app @ zero @ ( plus @ M2 @ M3 ) @ nil @ ( app @ M2 @ M3 @ L2 @ L3 ) )
= ( app @ ( plus @ zero @ M2 ) @ M3 @ ( app @ zero @ M2 @ nil @ L2 ) @ L3 ) ) ).
%------------------------------------------------------------------------------
Problems
ATP Systems and Tools
- DLash 1.11
- As an ATP system
- As a DHF type checker
- Available in SystemOnTPTP
- DT2H2X 1.8.4
- As an ATP system
- As a DHF type checker
- Available in SystemOnTPTP
- TPTP Utils (by Alex Steen)
- As a translator to plain THF (still to have Daniel's modifications merged)