A proof engine for the Calculus of Inductive Constructions, the type theory of Lean and Rocq, written
in the Wolfram Language. Terms are ordinary Wolfram Language expressions built from built-in symbols
(Function, Typed, ForAll, Implies, Equal, Plus, ...). A small trusted kernel checks them,
and tactics build proofs step by step in a notebook.
Status: prototype. The kernel, inductive families with generated recursors, structures with projections, elaboration, a prelude of logic, equality, natural numbers, decisions and lists, and eighteen tactics, four of them Wolfram oracles, work and are tested. It is pure Wolfram Language, with no native library underneath, and it does not depend on Lean. LeanLink's
LeanToTypeTheoryandTypeTheoryToLeantranslate declarations between Lean and TypeTheory; through them this kernel checks all of Lean'sInit.Prelude, 142 modules of Mathlib, from the logic ofNonemptyto the complex numbers, derivatives, logarithms and real powers, inner product spaces and the p-adic numbers, and the 11,167 constants underReal.sqrt_nonneg.
Install the published paclet:
PacletInstall[ResourceObject["https://www.wolframcloud.com/obj/wolframinstitute/DeployedResources/Paclet/WolframInstitute/TypeTheory"]]
Needs["WolframInstitute`TypeTheory`"]Or from a checkout:
PacletDirectoryLoad["path/to/TypeTheory/TypeTheory"]
Needs["WolframInstitute`TypeTheory`"]Loading takes about three and a half seconds, most of them building the prelude through the kernel.
The documentation site has a reference page for every symbol, a guide, and the tutorials Getting Started with TypeTheory, The Prelude, Instances and Coercions, The Integers, The Rationals, Rules and Computation, Erased and Affine Variables, Homotopy Type Theory, Cubical Type Theory and Mathlib in TypeTheory. The pages are literate Markdown in docs/paclet/en, written to docs/paclet/en/DOC_GUIDE.md, and PacletPage builds and publishes them:
wl -f build_docs.wls # evaluate the pages into notebooks under TypeTheory/Documentation
wl -f release.wls --dry-run # build and check the site and the paclet archive, deploying nothing
wl -f release.wls # publish the site and the paclet, as wolframinstituteA term carries the environment its constants come from. Without one, it is in the prelude, an environment of logic, equality and the natural numbers:
TypeOf[TypeTheoryTerm[2 + 3]]
(* ℕ, that is TypeTheoryTerm[NonNegativeIntegers, prelude] *)
WeakHeadNormalForm[TypeTheoryTerm[2 + 3]]
(* 5 *)Declarations are inert constructors until an environment checks them. TypeTheoryEnvironment[{...}]
gives the prelude extended with them, and Append extends any environment; neither changes the old one:
arithmetic = TypeTheoryEnvironment[{TypeTheoryTheorem[TwoPlusTwo, 2 + 2 == 4, EqualityReflexivity[4]]}];
arithmetic[TwoPlusTwo]
(* theorem TwoPlusTwo : 2 + 2 == 4 *)
TypeTheoryEnvironment[{TypeTheoryTheorem[Wrong, 2 + 2 == 5, EqualityReflexivity[4]]}]
(* Failure["TypeMismatch", ...]: EqualityReflexivity[4] has type 4 == 4, but the expected type is 2 + 2 == 5 *)A proof by induction, one tactic at a time:
proof = TypeTheoryProof[ForAll[{Typed[n, Naturals]}, 0 + n == n]];
proof = TypeTheoryTactic["Introduce", n][proof];
proof = TypeTheoryTactic["Induction", n][proof]; (* goals 0 + 0 == 0 and 0 + n == n ⇒ 0 + (n + 1) == n + 1 *)
proof = TypeTheoryTactic["Reflexivity"][proof]; (* 0 + 0 == 0 by computation *)
proof = TypeTheoryTactic["Introduce", k, ih][proof]; (* ih : 0 + k == k *)
proof = TypeTheoryTactic["Exact", EqualityCongruence[NaturalNumberSuccessor, ih]][proof];
proved = TypeTheoryEnvironment[{TypeTheoryTheorem[ZeroLeftIdentity, proof]}];
TypeTheoryCheck[TypeTheoryTerm[ZeroLeftIdentity[7], proved], TypeTheoryTerm[0 + 7 == 7]]
(* Success["TypeChecked", ...] *)In a notebook a proof shows its open goals, each as a list of hypotheses over the goal. A term shows
in mathematical notation, with ∧, ∨, ¬, and the natural numbers as 0 and n + 1 as Lean shows
them; a declaration shows as its keyword, its name and its type.
| Surface term | Meaning |
|---|---|
Function[{Typed[x, A], ...}, b] |
a function |
ForAll[{Typed[x, A], ...}, B] |
a dependent function type, or a universal statement |
Implies[A, B], TypeSpecifier[{A, ...} -> B], A -> B |
a function type whose result does not depend on the argument |
TypedImplicit[x, A] |
an implicit binder, filled in by elaboration; Annotation[Typed[x, A], kind] with "StrictImplicit" or "InstanceImplicit" gives the other kinds, an instance-implicit one filled in by an instance |
Exists[{Typed[x, A]}, p] |
an existential statement |
Typed[e, A] |
e, checked against A |
With[{x = v}, b] |
b with x standing for v |
TypeUniverse[level] |
a universe: TypeUniverse[0] is Prop, TypeUniverse[1] is Type, TypeUniverse[u + 1] |
f[a, b] |
application, curried, with implicit arguments filled in |
Construct[f, a, b] |
application with every argument given, implicit ones included |
Subscript[c, level, ...] |
the constant c at explicit universe levels |
t[[i]] |
field i of t, whose type is a structure |
0, 1, 2, ... |
natural number literals |
RightTee[{Typed[x, A], ...}, B] |
a goal, read as ForAll |
Any other symbol or string is a bound variable or a declared constant. A symbol whose value is a
TypeTheoryTerm stands for that term, one whose value is a finished TypeTheoryProof stands for its
proof, and one whose value is a declared constant stands for it, as Naturals = NonNegativeIntegers
does.
TypeTheoryTerm has the HoldFirst attribute. It has to: ForAll[Typed[x, A], B] on its own evaluates
to B, and n + 0 == n to True. The declaration constructors and TypeTheoryProof hold their terms
for the same reason. Names are kept in HoldComplete throughout, so a symbol with a value never
evaluates inside a term.
| Constructor | Declares |
|---|---|
TypeTheoryAxiom[name, type] |
an axiom |
TypeTheoryDefinition[name, value] |
a definition; value may be Typed[v, type]; "Instance" -> True makes it an instance of its type's class, "Coercion" -> True a coercion, and "Opaque" -> True a definition checked as any other that never unfolds, as Lean's opaque |
TypeTheoryTheorem[name, statement, proof] |
a theorem; TypeTheoryTheorem[name, proof] takes the statement of a finished proof |
TypeTheoryInductiveType[name, type, {c -> type, ...}] |
an inductive type with its constructors and its recursor InductiveRecursor[name]; {name -> type, ...} declares mutually inductive types |
TypeTheoryNaturalNumbers[type, zero, successor, <|role -> operation, ...|>] |
the natural numbers that literals belong to, and the operations computed on literals |
TypeTheoryRewriteRule[name, ForAll[binders, lhs -> rhs]] |
a computation rule for an axiom, where the rules allow it |
TypeTheoryQuotients[] |
the quotient types of Lean's kernel; TypeTheoryQuotients[equality, {type, introduction, lift, induction}] under other names |
TypeTheoryCubical[sum] |
the interval, paths, transport, composition and Glue types of cubical type theory, where the rules are cubical |
TypeTheoryEnvironment[{declaration, ...}] adds declarations in turn to the default environment, which is
also the environment of any term or proof that names none: the prelude, until
SetTypeTheoryEnvironment[env] makes env the default (SetTypeTheoryEnvironment["Prelude"] sets it
back, and Block[{$TypeTheoryEnvironment = env}, ...] sets it for one computation). TypeTheoryEnvironment[env, {declaration, ...}] adds
them to env, Append[env, declaration] adds one, TypeTheoryEnvironment[] is empty,
TypeTheoryEnvironment["Prelude"] is the prelude itself, TypeTheoryEnvironment["Constructive"] is
the prelude without its axioms, TypeTheoryEnvironment["HomotopyTypeTheory"] is homotopy type theory,
TypeTheoryEnvironment["Cubical"] is cubical type theory, and
TypeTheoryEnvironment[rules] is the empty environment of the given TypeTheoryRules. An environment behaves like an association of
its constants: env[name] gives the declaration that introduced name, and Keys, Length,
KeyExistsQ, Normal and Information work as expected. Normal[env] gives the declarations, the
prelude's included, written out exactly, so TypeTheoryEnvironment[TypeTheoryEnvironment[], Normal[env]]
rebuilds it.
An environment is a handle to a store: a symbol of its own whose DownValues hold the constants, the Wolfram Language's own way of storing definitions. The handle is small, so terms and proofs carry it. A store is never changed once built, and it lasts for the session.
TypeTheoryEnvironment["Integers"] is the prelude with the integers, built and checked the first time it
is asked for: classes of pairs of natural numbers (a, b), standing for a - b, a quotient type. The
operations are lifted from pairs, and the laws of a commutative ring, IntegerAdditionCommutativity
through IntegerDistributivity, are proved by the tactics themselves: "Induction" on each class,
QuotientSoundness, and "Ring" on the pairs. With those laws, "Ring" proves any identity of
commutative rings over the integers by normal forms of its own, as it does over the natural numbers;
IntegerEqualityDecidable decides their equations, so "Decide" proves a closed one. There +, *,
-, ^, the comparisons and negative literals are the integers' wherever the types say so, and a
natural number coerces to an integer:
integers = TypeTheoryEnvironment["Integers"];
TypeOf[TypeTheoryTerm[Function[{Typed[x, Integers], Typed[n, Naturals]}, 2 x - 7 <= x + n], integers]] (* ℤ → ℕ → Prop *)Squares are at least 0, IntegerSquareNonnegative, and IntegerLessEqualOfMultiple gives x <= y from
(d + 1) (y - x) == s with 0 <= s. "SumOfSquares" proves an inequality with them: Wolfram finds d
and a sum s of squares of polynomials, by exact linear algebra on a Gram matrix and, where it has free
entries, a diagonally dominant one from linear inequalities or else SemidefiniteOptimization; "Ring"
proves the equation:
TypeTheoryProof[ForAll[{Typed[x, Integers], Typed[y, Integers], Typed[z, Integers]}, x y + y z + z x <= x^2 + y^2 + z^2], integers, {
TypeTheoryTactic["Introduce", x, y, z],
TypeTheoryTactic["SumOfSquares"] (* 2 (x^2 + y^2 + z^2 - x y - y z - z x), a sum of three squares *)
}]TypeTheoryEnvironment["Rationals"] is the integers' environment with the rationals: classes of pairs
(a, b) of an integer and a natural number, standing for a / (b + 1), so no denominator is 0. The
operations are lifted from pairs, each respecting the relation by a polynomial combination of it that
"PolynomialReduce" finds over the integers, and the laws of a commutative ring, RationalAdditionCommutativity
through RationalDistributivity, are proved by "Induction" on each class, QuotientSoundness, and
"Ring" on the equation of integers it leaves. The inverse computes, by recursion on the pair of natural
numbers of the numerator, and RationalMultiplicationInverse proves x x^-1 == 1 for x not 0, which makes
the rationals a field; 0^-1 is 0. There +, *, -, /, ^, x^-1 and the comparisons are the
rationals' wherever the types say so, and an integer or a natural number coerces to a rational. "Ring"
proves identities of rationals by their classes, and RationalEqualityDecidable decides equations, so
"Decide" settles one of literals:
rationals = TypeTheoryEnvironment["Rationals"];
TypeTheoryProof[Typed[1/2 + 1/3, Rationals] == 5/6, rationals, {TypeTheoryTactic["Decide"]}] (* Proof complete *)
TypeTheoryProof[ForAll[{Typed[x, Rationals]}, x / 2 + x / 3 == 5 x / 6], rationals, {
TypeTheoryTactic["Introduce", x],
TypeTheoryTactic["Ring"] (* by the classes of x and of the fractions *)
}]Under TypeTheoryRules["CalculusOfInductiveConstructions", "Quantities" -> True] a binder may carry a
quantity, Typed[x, A, 0] or Typed[x, A, 1]: the code that runs never uses an erased variable, and uses
an affine one at most once, as in BendTT's affine type theory. The kernel counts the uses of each variable
outside the types, and function types differ by their quantities. The rules only reject more, so they are
as consistent as without quantities:
affine = TypeTheoryTranslate[TypeTheoryEnvironment["Prelude"], TypeTheoryRules["CalculusOfInductiveConstructions", "Quantities" -> True]]["Environment"];
TypeTheoryEnvironment[affine, {TypeTheoryDefinition[Twice, Function[{TypedImplicit[A, TypeUniverse[1], 0], Typed[f, TypeSpecifier[{A} -> A], 1], Typed[x, A]}, f[f[x]]]]}]
(* Failure["QuantityExceeded", ...]: f has quantity 1, but the code that runs uses it more than once *)TypeTheoryEnvironment["Cubical"] follows cubical type theory, after Cohen, Coquand, Huber and Mörtberg: a
path is a function of an interval, function extensionality and path induction are terms, transport and
composition compute by the type, and univalence is a path of Glue types along which transport applies the
equivalence. It has no axiom, so transport along univalence computes:
cubical = TypeTheoryEnvironment["Cubical"];
WeakHeadNormalForm[TypeTheoryTerm[CubicalTransport[EquivalenceToPath[NegationEquivalence], 0, "true"], cubical]] (* "false" *)Elaboration fills in what Lean's type classes and coercions do. An argument of an instance-implicit
binder, Annotation[Typed[h, class], "InstanceImplicit"], is a variable bound by such a binder, or else
the first definition declared with "Instance" -> True whose type unifies with the binder's, the latest
declared first, its own instance arguments found in turn. A term whose type does not unify with the one
expected is passed through a definition declared with "Coercion" -> True from the one type to the
other, or a chain of at most three. The kernel checks every term elaboration builds with them:
coerced = TypeTheoryEnvironment[{
TypeTheoryDefinition[NaturalOfBoolean, Function[{Typed[b, Booleans]},
InductiveRecursor[Booleans][Function[{Typed[t, Booleans]}, Naturals], 0, 1, b]], "Coercion" -> True]
}];
WeakHeadNormalForm[TypeTheoryTerm[NaturalNumberSuccessor["true"], coerced]] (* NaturalOfBoolean["true"] + 1 *)
WeakHeadNormalForm[TypeTheoryTerm[Decide[2 < 3 && 4 != 5]]] (* "true", by the instances of Decidable *)The prelude is the default environment, that of every term, proof and declaration list that names
none, unless SetTypeTheoryEnvironment sets another. Each of its
169 constants is checked by the kernel when the paclet loads. It is classical, as Lean's library is:
three constants are axioms, Lean's three, propositional extensionality, the soundness of quotients and
choice, and function extensionality and the excluded middle are proved from them. TypeTheoryEnvironment["Constructive"] is the prelude without the
axioms and what is proved from them, to prove theorems without axioms or to assume others. The tutorial
The TypeTheory Prelude on the documentation site goes through all of it.
- Logic:
True(TrueIntroduction),False(FalseElimination),Not,And(AndIntroduction,AndEliminationLeft,AndEliminationRight),Or(OrIntroductionLeft,OrIntroductionRight),Equivalent(EquivalentIntroduction,EquivalentForward,EquivalentBackward, with reflexivity, symmetry and transitivity) andExists(ExistsIntroduction). - Equality:
Equal(EqualityReflexivity,EqualitySymmetry,EqualityTransitivity,EqualityCongruence,EqualitySubstitution) andUnequal,x != y. - Functions:
IdentityandComposition. - Quotients: the quotient types of Lean's kernel,
QuotientType[r], withQuotientIntroduction,QuotientLiftandQuotientInduction, declared byTypeTheoryQuotients[]: a lift computes on a class, andQuotientSoundness, Lean'sQuot.sound, is an axiom. - Natural numbers:
NonNegativeIntegers, orNaturalsfor short, withNaturalNumberZero,NaturalNumberSuccessorandNaturalNumberPredecessor, registered so that literals are natural numbers;Plus,Times,PowerandSubtract(which stops at 0), each by recursion on its second argument as in Lean, and computed on literals with integers, as Lean's kernel computes them with GMP;LessEqual, inductive as Lean'sNat.le(LessEqualReflexivity,LessEqualStep), withLess,GreaterEqualandGreater. - Theorems about them: commutativity, associativity and distributivity of addition and multiplication, the zero, one and successor laws, cancellation of subtraction and of a positive factor, the laws of powers, injectivity of the successor, the order's transitivity, antisymmetry, irreflexivity and totality, and sums and multiples of inequalities.
- Booleans:
Booleans, with the constants"false"and"true", and"not","and"and"or", named by strings, by cases on the first argument as Lean'sBool.True,False,Not,AndandOrstand for them where a Boolean is expected, and they show astrue,false,!,&&and||. - Decisions:
Decidable(DecidableFalse,DecidableTrue), a class as Lean's, withDecide[p]giving the Boolean of the decision ofp, found among the instances, andDecideSoundnessthe proof from one that computes to"true", as Lean'sdecideandof_decide_eq_true. The instancesNaturalNumberEqualityDecidableandLessEqualDecidabledecide==and<=of natural numbers through the Boolean comparisons"equal"and"lessEqual", which the kernel computes on literals;NotDecidable,AndDecidableandOrDecidablecombine decisions, and"trueDecidable","falseDecidable"and"booleanEqualityDecidable"decideTrue,Falseand equations of Booleans. - Pairs, sums, options and lists:
CartesianProduct(Pair),DisjointUnion(LeftInjection,RightInjection),Option(OptionNone,OptionSome) andLists(EmptyList,ListPrepend), as Lean'sProd,Sum,OptionandList;Join,Length,Map,AppendandReverseon lists, and their lawsJoinEmptyRight,JoinAssociativity,LengthJoin,LengthMap,MapJoin,MapComposition,ReverseJoin,ReverseReverseandLengthReverse. - Classical logic:
Nonempty(NonemptyIntroduction) andSubtype(SubtypeIntroduction); the axiomsPropositionalExtensionality,QuotientSoundnessandChoice;ChosenWitnesswithChosenWitnessProperty; and the theoremsFunctionExtensionality, proved from the soundness of quotients as Lean proves it,ExcludedMiddle, proved by Diaconescu's argument, andDoubleNegationElimination.
The elaborator reads a - b as Subtract[a, b] and a && b && c as a && (b && c) for propositions
and (a && b) && c for Booleans. True, False, Not, And and Or are propositions or Booleans, as
the type decides: propositions where a type or Prop is expected, Booleans where Booleans is, and
otherwise whatever the arguments or the term's use allow. A term nothing decides, such as
True == False, is ambiguous and gives a Failure, and Typed[True, Booleans] says which it is.
The rules the kernel checks by are a value, TypeTheoryRules, which every environment carries:
"CalculusOfInductiveConstructions" for the prelude, "MartinLofTypeTheory", which has no Prop, and
"CubicalTypeTheory", Martin-Löf type theory with the primitives of cubical type theory. The setting
"Quantities" adds binders of quantity 0 and 1 to any of them.
Without Prop every universe is Type u, no two proofs of an equality are made equal, recursors
eliminate into Type u, and a theorem may state any type. TypeTheoryEnvironment[rules] starts an
environment of given rules, and the setting "RewriteRules" allows TypeTheoryRewriteRule declarations,
which give an axiom computation rules that weak head normalization and definitional equality use.
TypeTheoryEnvironment["HomotopyTypeTheory"] is homotopy type theory as in the HoTT book, on Martin-Löf
rules with rewrite rules: True, False and Not as types; Equal as the type of paths, with path
induction as its recursor; Transport and the operations on paths, which compute on reflexivity;
bi-invertible equivalences and the axiom Univalence, with UniverseNotSet proved from it; and the
circle, by axioms, with the rewrite rule CircleInductionBase making induction compute on its base
point. On the prelude's rules the same declarations with an equality in Prop prove False, which is why
the HoTT rules refuse one.
TypeTheoryTranslate[environment, rules] moves declarations between rules: it replays them on the
empty environment of rules, whose kernel checks each again, and leaves out what does not check with
whatever mentions it. Where the rules lose Prop, Prop becomes Type and a universe level l becomes
max(l, 1), recursor levels following; where they gain it, theorems become definitions. The
constructive prelude translates to Martin-Löf type theory but for the quotient types, and homotopy type
theory to the calculus of inductive constructions with rewrite rules. Axioms are kept only with
"Axioms" -> True, since propositional extensionality, for one, does not hold of types.
TypeTheoryTactic[name, arguments...][proof] works on the first goal of a TypeTheoryProof:
| Tactic | Effect |
|---|---|
"Introduce", x, ... |
moves the variables or hypotheses of a universal statement, implication or Not into the context |
"Exact", term |
solves the goal with a term |
"Apply", term |
solves the goal with a term applied to new goals, as many as its conclusion needs |
"Reflexivity" |
solves a == b when the two sides are equal by computation |
"Induction", x |
one goal per constructor of the type of x, with induction hypotheses; the indices of an inductive family must be variables, and the hypotheses that depend on x are generalized; on a class of a quotient, one goal for the class of an element |
"Cases", x |
one goal per constructor of the type of x, without induction hypotheses |
"Generalize", h, ... |
moves the hypotheses h, ..., with those that depend on them, back into the goal |
"Constructor" |
applies the first constructor of the goal's inductive type that applies |
"Assumption" |
solves the goal with a hypothesis |
"Rewrite", h |
rewrites the goal with the equation h, left to right, or right to left with "RightToLeft"; "At" -> k rewrites the hypothesis k instead |
"Change", statement |
replaces the goal by a statement equal to it by computation |
"Simplify", {h, ...} |
rewrites with the equations until none applies, unfolds each definition among them where it computes, and closes an equation whose sides are equal by computation |
"Decide" |
proves a closed statement by computing its decision, the instance of Decidable that elaboration finds: the prelude's decide == and <= of natural numbers and the connectives |
"Ring" |
proves an equation of natural numbers that holds in every commutative semiring, by normal forms with proofs from the prelude's laws |
"FindInstance" |
proves an existential statement over the natural numbers with witnesses that Wolfram's FindInstance finds |
"PolynomialReduce" |
proves an equation from the equations among the hypotheses, by a polynomial combination whose cofactors Wolfram finds |
"LinearArithmetic" |
proves an inequality, an equation or False from the inequalities and equations among the hypotheses, by a linear combination whose multipliers Wolfram finds |
"FindEquationalProof" |
proves an equation from equations for all values among the hypotheses, by replaying the proof Wolfram's FindEquationalProof finds |
"SumOfSquares" |
proves an inequality of integers, or of natural numbers, in TypeTheoryEnvironment["Integers"] by a sum of squares that Wolfram finds, a positive multiple of the larger side less the smaller |
TypeTheoryProof[statement, env, {tactic1, tactic2, ...}] runs a list of tactics. Nothing a tactic does
is trusted: the finished term is checked by the kernel when the theorem is added to an environment.
"Simplify" unfolds a definition by recursion where it computes, as Lean's simp [f] does, and folds
its recursive calls back, so the laws of lists go through with induction and simplification alone:
TypeTheoryProof[ForAll[{Typed[a, Lists[Naturals]], Typed[b, Lists[Naturals]], Typed[c, Lists[Naturals]]}, Join[Join[a, b], c] == Join[a, Join[b, c]]], {
TypeTheoryTactic["Introduce", a, b, c],
TypeTheoryTactic["Induction", a],
TypeTheoryTactic["Simplify", {Join}], (* Join[EmptyList, m] is m *)
TypeTheoryTactic["Introduce", x, rest, ih],
TypeTheoryTactic["Simplify", {Join, ih}] (* Join[ListPrepend[x, l], m] is ListPrepend[x, Join[l, m]] *)
}]"FindInstance", "PolynomialReduce", "LinearArithmetic", "FindEquationalProof" and "SumOfSquares"
ask Wolfram for what a proof needs: witnesses, the cofactors or multipliers of a combination of the
hypotheses, a proof by completion from equational hypotheses, or a sum of squares. The kernel checks the proof built from the answer:
TypeTheoryProof[Exists[{Typed[x, Naturals], Typed[y, Naturals]}, And[x^2 + y^2 == 25, 0 < x, x < y]], {
TypeTheoryTactic["FindInstance"] (* x = 3, y = 4, checked by computing *)
}]
TypeTheoryProof[ForAll[{Typed[x, Naturals], Typed[y, Naturals]}, Implies[x + y == 10, Implies[x == 2 y + 1, x y == 21]]], {
TypeTheoryTactic["Introduce", x, y, h, k],
TypeTheoryTactic["PolynomialReduce"] (* cofactors over thirds, checked by "Ring" *)
}]TypeTheory/Kernel/
Terms/CoreTerms.wl core terms (locally nameless) and universe levels
Terms/SurfaceSyntax.wl held syntax trees; reading core terms back, for display or exactly
Terms/Formatting.wl notebook display of terms, declarations and proofs
Checking/Rules.wl the rules an environment is checked by: TypeTheoryRules
Checking/TypeChecking.wl the kernel: inference, reduction, definitional equality, projections
Checking/InductiveTypes.wl checking inductive families and generating recursors
Checking/NaturalNumbers.wl registering the natural numbers for literals
Checking/Quotients.wl the quotient types of Lean's kernel, and their computation
Checking/Quantities.wl binder quantities and the live check of erased and affine variables
Checking/Cubical.wl the interval, paths, transport, composition and Glue types
Checking/Environment.wl environments as stores of definitions, and kernel failures
Checking/Declarations.wl the declaration constructors and environments built from them
Checking/Queries.wl TypeOf, TypeTheoryCheck, DefinitionallyEqualQ, WeakHeadNormalForm, environments as associations
Elaboration/Elaboration.wl implicit arguments, instances, coercions, universe levels, unification
Proofs/ProofStates.wl proof states and tactics
Proofs/Ring.wl polynomial identities, with proofs from the prelude's laws
Proofs/Equational.wl the proofs of FindEquationalProof, replayed
Proofs/SumsOfSquares.wl sums of squares of polynomials, found from Gram matrices
Library/Prelude.wl the prelude
Library/HomotopyTypeTheory.wl the homotopy type theory environment
Library/Integers.wl the integers, a quotient, with their laws proved by the tactics
Library/Rationals.wl the rationals, a quotient over the integers, with their laws and inverse
Library/Cubical.wl the cubical environment: paths, equivalences and univalence that computes
The trusted part is CoreTerms.wl, TypeChecking.wl, InductiveTypes.wl, NaturalNumbers.wl,
Quotients.wl, Quantities.wl, Cubical.wl, Environment.wl and the core declaration functions: about
4,000 lines with their comments and usage messages, a thousand of them the cubical rules, which an
environment uses only under cubical rules. Elaboration and tactics produce terms that the kernel checks again with no metavariables
left, so a mistake outside the kernel can make a proof fail but cannot make a false statement a theorem.
Kernel answers are Failure objects, never messages.
Definitional equality unfolds definitions lazily, as Lean's kernel does: of two applications of different definitions, the one whose definition is higher, defined in terms of the other, unfolds one step, and the two are compared again, so that two applications of the same definition are compared by their arguments before either computes. A definition's height is one more than the greatest height of the definitions its value mentions.
A store can be changed by hand. TypeTheoryCheck[environment] replays every declaration from scratch
and compares each stored record with the record that checking it produces, so a forged theorem or
recursor is caught. See docs/notes/Kernel.md for the design decisions, and
docs/research/TypeTheoryEngine.html for the full design.
wolframscript -f scripts/run_tests.wlsThe suite has 309 tests in TypeTheory/Tests/, mirroring the kernel layout. They include rejecting
forged declarations: a wrong proof, a negative occurrence, an oversized universe, large elimination
from Or, data projected out of a proof, Type : Type, a lift of a quotient whose proof is wrong, an
equality that is not the identity type, a definition that copies an affine variable, a recursion on an
affine number, a transport along a line that is not constant on its face, and tampered environment
records; and, on the prelude's rules, the HoTT library proving False with an equality in Prop.
- Deciding the order of the integers and the rationals; normal forms of the rationals' own in
"Ring"; sums of squares with rational coefficients, and inequalities from hypotheses by the Positivstellensatz. - Induction on mutual or nested types, and on indexed families whose indices are not variables, in the tactic.
- Composition in a universe and higher inductive types in the cubical rules, so that transport along a concatenation of univalence paths computes; truncations; BendTT's own relaxations, a universe in itself and no positivity, which its consistency proof covers and these rules do not.
- Higher-order unification beyond patterns.
- A compiled kernel (
FunctionCompileover an array encoding of terms).