LeanLink — Exploring Mathlib

Prerequisites: Installing Mathlib
Install elan (Lean version manager) if not already installed:
(* Terminal: curl https://elan.lean-lang.org/install.sh | sh *)
Create a Lean project with Mathlib as a dependency and build the modules used in this notebook:
(* Terminal:
mkdir -p ~/src/mathlib4 && cd ~/src/mathlib4
lake init MathlibTest math
lake exe cache get
lake build Mathlib.Tactic.Ring
lake build Mathlib.Algebra.Group.Basic
lake build Mathlib.Logic.Basic
lake build Mathlib.FieldTheory.IsAlgClosed.Basic
*)
Setup
(*PacletDirectoryLoad[NotebookDirectory[]//ParentDirectory];*)​​PacletInstall["https://www.wolframcloud.com/obj/nikm/LeanLink.paclet",ForceVersionInstall->True]
Out[]=
PacletObject
Name: LeanLink
Version: 0.2.0

Get["LeanLink`"];​​mathlibDir=FileNameJoin[{$HomeDirectory,"src","mathlib4"}];
Part 1: Types and Propositions
In Lean 4 (and Mathlib), every expression has a type. Propositions live in
Prop
, data types live in
Type u
. LeanLink lets us inspect these directly.

Loading an environment

algEnv=LeanImport["Mathlib.Algebra.Group.Basic",​​"ProjectDir"->mathlibDir]
Out[]=
LeanEnvironment
Constants: 146679
Kinds: 4514 constructor72739 theorem63347 def3151 opaque2910 inductive14 axiom4 quot
This object cannot be used as input.

Length[algEnv]
Out[]=
115060

Reading a theorem's type

mul_comm
states that multiplication is commutative. Its type is the proposition it proves:
algEnv["mul_comm"]["TypeForm"]
Out[]=
∀ {G : Type u_1} [inst : CommMagma G] (a : G) (b : G), a * b = b * a
Compare with
add_zero
— adding zero on the right:
algEnv["add_zero"]["TypeForm"]
Out[]=
∀ {M : Type u} [inst : AddZeroClass M] (a : M), a + 0 = a
And
one_mul
— multiplying by one on the left:
algEnv["one_mul"]["TypeForm"]
Out[]=
∀ {M : Type u} [inst : MulOneClass M] (a : M), 1 * a = a

The expression tree

Behind the pretty-printed string is a symbolic expression tree.
"Type"
returns it:
algEnv["mul_comm"]["Type"]
Out[]=
{G:Sortu_1+1}[inst:
CommMagma
#0
](a:
#1
)(b:
#2
)
Eq
#3
HMul.hMul
#3
#3
#3
instHMul
#3
CommMagma.toMul
#3
#2
#1
#0
HMul.hMul
#3
#3
#3
instHMul
#3
CommMagma.toMul
#3
#2
#0
#1
Every Lean expression is built from a small set of constructors:
LeanConst
(named constant),
LeanApp
(function application),
LeanForall
(universal quantifier / function type),
LeanBVar
(bound variable),
LeanLambda
, and
LeanSort
.
Part 2: Understanding Binder Annotations
Lean uses three kinds of argument brackets:
◼
  • (x : T)
    — explicit: the caller must provide this
  • ◼
  • {x : T}
    — implicit: Lean infers this from context
  • ◼
  • [inst : T]
    — instance: Lean finds this via typeclass search
  • The new
    "Parameters"
    property peels apart the forall chain and shows each argument:
    algEnv["mul_comm"]["Parameters"]//Dataset
    Out[]=
    Name
    Type
    TypeForm
    Binder
    G
    Sort
    u_1
    +1
    Type u_1
    implicit
    inst._@.Mathlib.Algebra.Group.Defs.544328808._hygCtx._hyg.3
    CommMagma
    #0
    CommMagma #0
    instance
    a
    #1
    #1
    explicit
    b
    #2
    #2
    explicit
    The output tells us: to use
    mul_comm
    , we provide two explicit values
    a
    and
    b
    , and Lean auto-resolves the type
    G
    (implicit) and the
    CommMagma
    instance.

    Comparing parameter structures

    algEnv["add_zero"]["Parameters"]//Dataset
    Out[]=
    Name
    Type
    TypeForm
    Binder
    M
    Sort
    u
    +1
    Type u
    implicit
    inst._@.Mathlib.Algebra.Group.Defs.1575903989._hygCtx._hyg.4
    AddZeroClass
    #0
    AddZeroClass #0
    instance
    a
    #1
    #1
    explicit
    add_zero
    needs an
    AddZeroClass
    instance — Lean will find this automatically for types like
    Nat
    ,
    Int
    ,
    Real
    .
    algEnv["neg_add_cancel"]["Parameters"]//Dataset
    Out[]=
    Name
    Type
    TypeForm
    Binder
    G
    Sort
    u_1
    +1
    Type u_1
    implicit
    inst._@.Mathlib.Algebra.Group.Defs.108010751._hygCtx._hyg.3
    AddGroup
    #0
    AddGroup #0
    instance
    a
    #1
    #1
    explicit
    neg_add_cancel
    requires an
    AddGroup
    — a monoid with additive inverses.
    Part 3: Typeclasses
    Typeclasses are Lean's way of expressing algebraic structure. When you see
    [inst : Field k]
    , Lean automatically searches for a proof that
    k
    is a field.

    What typeclasses does
    mul_comm
    need?

    Select[algEnv["mul_comm"]["Parameters"],#Binder=="instance"&]//Dataset
    Out[]=
    Name
    Type
    TypeForm
    Binder
    inst._@.Mathlib.Algebra.Group.Defs.544328808._hygCtx._hyg.3
    CommMagma
    #0
    CommMagma #0
    instance

    What typeclasses does
    sub_eq_add_neg
    need?

    algEnv["sub_eq_add_neg"]["Parameters"]//Dataset
    Out[]=
    Name
    Type
    TypeForm
    Binder
    G
    Sort
    u_1
    +1
    Type u_1
    implicit
    inst._@.Mathlib.Algebra.Group.Defs.1234330678._hygCtx._hyg.3
    SubNegMonoid
    #0
    SubNegMonoid #0
    instance
    a
    #1
    #1
    explicit
    b
    #2
    #2
    explicit

    Building a typeclass hierarchy

    Each typeclass extends others. An
    AddGroup
    extends
    AddMonoid
    extends
    AddZeroClass
    . We can see this by inspecting the type of the typeclass itself:
    algEnv["AddGroup"]["TypeForm"]
    Out[]=
    ∀ (A : Type u), Type u
    Part 4: Propositional Logic
    logicEnv=LeanImport["Mathlib.Logic.Basic",​​"ProjectDir"->mathlibDir]
    Out[]=
    LeanEnvironment
    Constants: 139239
    Kinds: 4130 constructor70646 theorem58837 def2978 opaque2630 inductive14 axiom4 quot
    This object cannot be used as input.
    

    The law of excluded middle

    Every proposition is either true or false:
    logicEnv["Classical.em"]["TypeForm"]
    Out[]=
    ∀ (p : Prop), p ∨ ¬p
    logicEnv["Classical.em"]["Parameters"]//Dataset
    Out[]=
    Name
    Type
    TypeForm
    Binder
    p
    Prop
    Prop
    explicit

    Commutativity of connectives

    Double negation

    Part 5: Interactive Proofs
    LeanLink can open any theorem as a proof goal and let you step through it with tactics.

    Opening a proof goal

    Applying tactics

    Introduce the universally quantified variables:
    Part 6: The Fundamental Theorem of Algebra

    All IsAlgClosed theorems

    The core theorem: existence of roots

    Dissecting the FTA parameters

    Reading the parameter table:

    The conclusion

    After all the parameters, the return type (the thing being proved) is:

    Every polynomial splits

    A stronger form: every polynomial factors completely over an algebraically closed field:

    Consequences

    N-th roots exist in algebraically closed fields:
    Square roots exist:
    Algebraically closed fields are necessarily infinite:

    The construction of the typeclass

    Expression tree of the FTA

    Open the proof goal:
    The state shows the goal we need to prove. Not yet complete:
    Introduce the variables:
    Close it with the axiom: