Wolfram Language Paclet Repository

Community-contributed installable additions to the Wolfram Language

Primary Navigation

    • Cloud & Deployment
    • Core Language & Structure
    • Data Manipulation & Analysis
    • Engineering Data & Computation
    • External Interfaces & Connections
    • Financial Data & Computation
    • Geographic Data & Computation
    • Geometry
    • Graphs & Networks
    • Higher Mathematical Computation
    • Images
    • Knowledge Representation & Natural Language
    • Machine Learning
    • Notebook Documents & Presentation
    • Scientific and Medical Data & Computation
    • Social, Cultural & Linguistic Data
    • Strings & Text
    • Symbolic & Numeric Computation
    • System Operation & Setup
    • Time-Related Computation
    • User Interface Construction
    • Visualization & Graphics
    • Random Paclet
    • Alphabetical List
  • Using Paclets
    • Get Started
    • Download Definition Notebook
  • Learn More about Wolfram Language

LeanLink

Tutorials

  • Checking Mathlib with TypeTheory
  • Exploring Mathlib with LeanLink
  • An Import Graph for Mathlib
  • Getting Started with LeanLink

Guides

  • Lean 4 from the Wolfram Language

Symbols

  • ImportDOT
  • LeanApp
  • LeanBuild
  • LeanBVar
  • LeanCallGraph
  • LeanCompile
  • LeanConstantInfo
  • LeanConstant
  • LeanConst
  • LeanEnvironment
  • LeanEvaluate
  • LeanExport
  • LeanExportString
  • LeanExprGraph
  • LeanExpr
  • LeanForall
  • LeanFreeEnvironment
  • LeanFVar
  • LeanGoal
  • LeanImport
  • LeanImportString
  • LeanLam
  • LeanLet
  • LeanLevelIMax
  • LeanLevelMax
  • LeanLevelMVar
  • LeanLevelParam
  • LeanLevelSucc
  • LeanLevelZero
  • LeanListConstants
  • LeanListTheorems
  • LeanLitNat
  • LeanLitStr
  • LeanLoadEnvironment
  • LeanMVar
  • LeanNoValue
  • LeanProj
  • LeanSort
  • LeanState
  • LeanTactic
  • LeanTerm
  • LeanToFunction
  • LeanToTypeTheory
  • LeanTruncated
  • LeanValue
  • ProofToLean
  • TypeTheoryToLean

Checking Mathlib with TypeTheory

Prerequisites
Checking It Again
Loading a Module
Quotients
Checking It in TypeTheory
Lean's Prelude
A Theorem in TypeTheory
Beyond the Prelude
LeanLink loads a module of Mathlib straight from a built checkout, and
LeanToTypeTheory
imports its constants, each with every constant it depends on, into an environment of WolframInstitute/TypeTheory, a proof engine written in the Wolfram Language. TypeTheory's kernel checks every declaration again, independently of Lean's. This tutorial checks a whole module of Mathlib,
Mathlib.Basic.Nonempty
, and shows what TypeTheory does not check yet.

Prerequisites

The module comes from a built Mathlib checkout, as in the tutorial Exploring Mathlib with LeanLink, and the paclet
WolframInstitute/TypeTheory
must be installed:
In[1]:=
mathlibDir=FileNameJoin[{$HomeDirectory,"src","mathlib4"}];​​mathlibReady=DirectoryQ[FileNameJoin[{mathlibDir,".lake","build"}]]
Out[1]=
True

Loading a Module

Mathlib.Basic.Nonempty
imports nothing of Mathlib but its initialization, so it sits at the bottom of the library.
LeanImport
loads it with everything it imports:
In[2]:=
module="Mathlib.Basic.Nonempty";​​lean=IfmathlibReady,
LeanImport
[module,"ProjectDir"mathlibDir],
Out[2]=
LeanEnvironment
Constants: 97866
Kinds: 42074 def2939 constructor48937 theorem2012 opaque1888 inductive12 axiom4 quot
This object cannot be used as input.

The module's own constants are those whose
"Module"
it is:
In[3]:=
own=Select[Keys[lean],lean[#]["Module"]===module&];​​Length[own]
Out[3]=
37
They are theorems and definitions about
Nonempty
, such as this one, which says that a statement about every proof that a type is inhabited is a statement about every element:
In[4]:=
lean["Nonempty.forall"]["TypeForm"]
Out[4]=
∀ {α : Sort u_3} {p : Nonempty α → Prop}, (∀ (h : Nonempty α), p h) ↔ ∀ (a : α), p ⋯

Checking It in TypeTheory

LeanToTypeTheory
imports the 37 constants, and with them every constant they depend on, from Lean's core library and Mathlib's, into one environment, which TypeTheory's kernel checks declaration by declaration:
In[5]:=
checked=
LeanToTypeTheory
[lean,own]
Out[5]=
TypeTheoryEnvironment
Constants: 155
Theorems: 39

What the environment holds, by kind; each inductive type comes with its constructors and the recursor TypeTheory generates for it, which the import compares with Lean's:
In[6]:=
Information[checked,"Kinds"]
Out[6]=
InductiveType19,Constructor21,Recursor19,Axiom2,Definition55,Theorem39
The module assumes two of Lean's axioms, and nothing else:
In[7]:=
Information[checked,"Axioms"]
Out[7]=
{propext,Classical.choice}

A Theorem in TypeTheory

Lean names stay strings in TypeTheory. The statement of
Nonempty.forall
, as TypeTheory has checked it:
In[8]:=
TypeTheoryCheck[TypeTheoryTerm["Nonempty.forall",checked]]
Out[8]=
∀
{α:Sortu_3}
∀
{p:Nonempty[α]→Prop}
Iff
∀
h:Nonempty[α]
p[h],
∀
a:α
p[Nonempty.intro[a]]
A definition shows its value, here the choice of an element from an instance of
Nonempty
:
In[9]:=
checked["Classical.arbitrary"]
Out[9]=
definition
Classical.arbitrary
:
∀
α:Sortu_3
∀
[h:Nonempty[α]]
α:=(α:Sortu_3)[h:Nonempty[α]]↦Classical.choice[h]
Lean's notation, such as
↔
for
Iff
, belongs to Lean's syntax, not to its constants. TypeTheory shows a constant applied to its explicit arguments by giving that expression to
MakeBoxes
, so definitions of
MakeBoxes
give a Lean name, a string, a notation:
In[10]:=
MakeBoxes["Iff"[a_,b_],form_]:=MakeBoxes[Equivalent[a,b],form];​​MakeBoxes["Eq"[a_,b_],form_]:=MakeBoxes[ab,form];​​MakeBoxes["Or"[a_,b_],form_]:=MakeBoxes[Or[a,b],form];​​TypeTheoryCheck[TypeTheoryTerm["Nonempty.forall",checked]]
Out[10]=
∀
{α:Sortu_3}
∀
{p:Nonempty[α]→Prop}

∀
h:Nonempty[α]
p[h]⧦
∀
a:α
p[Nonempty.intro[a]]

Checking It Again

The environment can be checked again from scratch:
TypeTheoryCheck
replays every declaration on an empty environment and compares what it gets with what is stored:
In[11]:=
TypeTheoryCheck[checked]
Out[11]=
Success
✓
Message: All 155 constants of the environment check again from their declarations.
Constants: 155


Quotients

Lean's kernel has quotient types built in: lifting a function to a quotient and applying it to a class gives the function's value.
funext
is proved with them. TypeTheory's kernel has the same quotient types, and the import declares Lean's as TypeTheory's own:
In[12]:=
funext=
LeanToTypeTheory
[lean,"funext"]
Out[12]=
TypeTheoryEnvironment
Constants: 12
Theorems: 2

The four constants come from one declaration, with Lean's names and Lean's equality:
In[13]:=
funext["Quot.lift"]
Out[13]=
TypeTheoryQuotients[Eq,{Quot,Quot.mk,Quot.lift,Quot.ind}]
The kernel computes with them, so the cone needs no rewrite rule:
In[14]:=
Information[funext,"RewriteRules"]
Out[14]=
{}

Lean's Prelude

Lean's first file,
Init.Prelude
, depends on 1,404 constants, and TypeTheory checks them all. Three things in it go beyond an inductive family of one type and a sum of literals, and the import follows Lean's kernel in each.
Lean's syntax trees are a nested inductive type: a node holds an array of trees. TypeTheory checks the nesting as Lean's kernel does, and generates a recursor on each container the trees are nested in, the array and the list inside it, which the import compares with Lean's
Lean.Syntax.rec_1
and
Lean.Syntax.rec_2
:
In[15]:=
syntax=
LeanToTypeTheory
[lean,"Lean.Syntax"]
Out[15]=
TypeTheoryEnvironment
Constants: 378
Theorems: 49

The recursors of
Lean.Syntax
, one for the type and one for each container:
In[16]:=
Select[Keys[syntax],MatchQ[InductiveRecursor["Lean.Syntax",___]]]
Out[16]=
{InductiveRecursor[Lean.Syntax],InductiveRecursor[Lean.Syntax,1],InductiveRecursor[Lean.Syntax,2]}
A string literal is the list of its characters, as Lean's kernel reads it, so the names of the syntax kinds import:
In[17]:=
kinds=
LeanToTypeTheory
[lean,"Lean.nullKind"]
Out[17]=
TypeTheoryEnvironment
Constants: 385
Theorems: 61

The name of the null kind, a list of characters:
In[18]:=
kinds["Lean.nullKind"]
Out[18]=
definition
Lean.nullKind
:
Lean.SyntaxNodeKind:=Lean.Name.mkStr1[String.ofList[List.cons[Char.ofNat[110],List.cons[Char.ofNat[117],List.cons[Char.ofNat[108],List.cons[Char.ofNat[108],List.nil]]]]]]
And Lean's kernel computes
Nat.add
,
Nat.mul
,
Nat.ble
and the other operations on natural number literals with GMP. The import registers each with TypeTheory, which then computes it with integers, so a statement about the size of machine words, 2^32 or 2^64, checks at once:
In[19]:=
words=
LeanToTypeTheory
[lean,"USize.size_eq"]
Out[19]=
TypeTheoryEnvironment
Constants: 117
Theorems: 12

The statement, checked:
In[20]:=
TypeTheoryCheck[TypeTheoryTerm["USize.size_eq",words]]
Out[20]=
USize.sizeOfNat.ofNat[4294967296]∨USize.sizeOfNat.ofNat[18446744073709551616]

Beyond the Prelude

LeanLink's repository has a script,
typetheory_coverage.wls
, that imports every constant of a list of modules, with what it depends on in order, into one TypeTheory environment and reports what checks. The 25 modules at the bottom of Mathlib, from the logic of
Nonempty
and unique existence to options, orderings and folds over lists, check completely, with all 5,361 constants they depend on, in about three and a half minutes. So do 117 modules higher up, each with every constant it depends on, among them the real and complex numbers, the exponential, logarithm and trigonometric functions, real powers, derivatives, polynomials, matrices and determinants, ideals, separable field extensions, Sylow's theorems, primes and factorizations, cardinals, simple graphs, measurable, metric, uniform and inner product spaces, normed fields, compactness and the p-adic numbers.
Real.sqrt_nonneg
checks too, with the 11,167 constants it depends on through Mathlib's construction of the real numbers, in about seven minutes.
TypeTheory rejects none of these constants. Of the 71,203 distinct constants these modules and quadratic reciprocity depend on, six do not check within the five minutes the script allows each constant, and the 251 that depend on them are left unchecked: five proofs by
decide
that characters of
ZMod4
and
ZMod8
are 0 off the units, in the cone of quadratic reciprocity, and the associativity of multiplication in a tensor product of algebras. A proof that a tactic writes shares its subterms in Lean, and the import shares them too, reading and translating each distinct subterm once: a proof that
omega
writes in Lean's
Init.Data.Array.Extract
has 19 million nodes written out and 123 distinct ones, and a proof that
grind
writes in
Mathlib.Data.Int.Init
checks, with the 3,201 constants it depends on, in under two minutes.
RelatedGuides
▪
Lean 4 from the Wolfram Language

© 2026 Wolfram. All rights reserved.

  • Legal & Privacy Policy
  • Contact Us
  • WolframAlpha.com
  • WolframCloud.com