Zulip Chat Archive
Stream: Type theory
Topic: Can ZFC model restricted Lean?
Mirek Olšák (Dec 01 2025 at 19:55):
I thought this could be well-known among type theorists. I have two restrictions in mind
- No inductive types & no choice (not even unique choice)
- The same as (1) but we allow the inductive type Nat (and recursion on it).
The question is whether Lean's type theory restricted in such way can be modeled inside ZFC (without inaccessibles).
Intuitively, well-founded recursion and unique choice are the constructs that allow building crazily large objects, so I wonder if without them we cannot get too high, and actually don't need inaccessibles, or if more levels of the universe hierarchy can somehow compensate for the restrictions.
To my knowledge, @Mario Carneiro formalized ZFC in Lean without much inductives but choice was fundamental there, right?
Mario Carneiro (Dec 01 2025 at 19:56):
This sounds like MLTT, which is known to be interpretable inside second order arithmetic. See:
Mario Carneiro (Dec 01 2025 at 19:59):
actually you may need to ban Prop as well (i.e. impredicativity) to get the usual MLTT
Mirek Olšák (Dec 01 2025 at 20:13):
MLTT sounds like a good start but I was imagining if there was some way to model it with "bounded" functions (where I don't know how to define boundedness well). Intuitively, it should be fine to add almost all the classical features such as impredicativity, excluded middle, decidability, quotients, perhaps even a Quotient.choice. Only I don't want to allow functions to grow too fast. Of course, unique choice must be forbidden for that reason (because it can find something extremely large only because it exists).
Mario Carneiro (Dec 01 2025 at 20:14):
I don't think lean allows you to build fast growing functions through unique choice
Mario Carneiro (Dec 01 2025 at 20:14):
the only functions you can prove exist this way you can already construct directly AFAIK
Mirek Olšák (Dec 01 2025 at 20:15):
Unique choice with Quotient allows you to build ordinals, no?
Mirek Olšák (Dec 01 2025 at 20:15):
I agree that without Quotient, you cannot select the specific big type.
Aaron Liu (Dec 01 2025 at 20:15):
without inductive types I don't think you can build very big ordinals
Mario Carneiro (Dec 01 2025 at 20:16):
quotients don't let you do anything new either, you just work with setoids instead
Mirek Olšák (Dec 01 2025 at 20:17):
I can define well founded recursion using unique choice without inductives.
Mirek Olšák (Dec 01 2025 at 20:17):
that is the standard ZFC way
Mario Carneiro (Dec 01 2025 at 20:18):
in a world without prop, well founded recursion is tautological
Mario Carneiro (Dec 01 2025 at 20:18):
since recursion is what it means for a type to be inductive
Mario Carneiro (Dec 01 2025 at 20:23):
Mirek Olšák said:
I can define well founded recursion using unique choice without inductives.
that's how it's done in my ZFC without inductives thing
Mario Carneiro (Dec 01 2025 at 20:25):
I think you might be right, you basically don't have any kind of induction so you can bound type sizes as one does in HOL
Mario Carneiro (Dec 01 2025 at 20:26):
and even if you have Nat you can still bound type sizes under iterations
Mirek Olšák (Dec 01 2025 at 20:27):
Yes, that is my intuition but I am not sure how to prove it.
Mario Carneiro (Dec 01 2025 at 20:27):
if you don't have well founded recursion you don't get to turn a large universe into a tall ordinal hierarchy, so it just becomes a matter of bounding ranks and determining what we are looking at
Mario Carneiro (Dec 01 2025 at 20:28):
One universe bounding argument which is similar to HOL's but deals with dependent types is the one for PVS
Mirek Olšák (Dec 01 2025 at 20:29):
do you have a link?
Mario Carneiro (Dec 01 2025 at 20:30):
https://pvs.csl.sri.com/doc/semantics.pdf
Mario Carneiro (Dec 01 2025 at 20:37):
the relevant stuff is on page 34-37
James E Hanson (Dec 02 2025 at 01:28):
Mario Carneiro said:
that's how it's done in my ZFC without inductives thing
Where is this, by the way?
Mirek Olšák (Dec 02 2025 at 01:47):
Mario Carneiro said:
It seems to me that PVS doesn't have universes, without them, it is relatively straightforward. I mostly struggle to define what functions in a higher universes to allow. For example, I cannot allow Type -> Type to contain all mathematical functions because then I could use that to define a cofinal sequence Nat -> Type...
Mario Carneiro (Dec 02 2025 at 02:22):
James E Hanson said:
Mario Carneiro said:
that's how it's done in my ZFC without inductives thing
Where is this, by the way?
Mario Carneiro (Dec 02 2025 at 02:24):
Mirek Olšák said:
Mario Carneiro said:
It seems to me that PVS doesn't have universes, without them, it is relatively straightforward. I mostly struggle to define what functions in a higher universes to allow. For example, I cannot allow
Type -> Typeto contain all mathematical functions because then I could use that to define a cofinal sequenceNat -> Type...
Not sure I follow this. The basic pattern is that these types consist of large sets of small rank, like the low levels of the beth hierarchy. The point is that it doesn't matter if you can construct cofinal sequences because there is no union-like operator, everything you construct is uniformly bounded
Mario Carneiro (Dec 02 2025 at 02:30):
The easy solution for Type is to just say that universe-making is an operator which bumps the cofinality and don't worry too much about it. So you get something like or for everything except universes and then you just get a cardinal as a bound on the rank of the next layer building up to Type 1 (and then you stack another layers of pis and such on top on your way to Type 2), and so on.
Mario Carneiro (Dec 02 2025 at 02:31):
that's probably overkill and you can get away with less if you have Type -> Type functions be some kind of uniformly bounded function type
Bas Spitters (Dec 02 2025 at 09:44):
There's this work by Bruno Barras: https://jfr.unibo.it/article/download/1695/1316
I recall follow-up work, but I currently cannot find it.
Mirek Olšák (Dec 02 2025 at 10:07):
Mario Carneiro said:
Not sure I follow this. The basic pattern is that these types consist of large sets of small rank, like the low levels of the beth hierarchy. The point is that it doesn't matter if you can construct cofinal sequences because there is no union-like operator, everything you construct is uniformly bounded
I just think it is not that simple (and was arguing about it with chatbots for a while). Even if we model Type with , there is a set of cardinality at least there. So in case my model has a function covering all the for , I have a problem, because I should at least allow a forall type ∀ x : X, f x, which I cannot model.
Sure, so this cannot be in the model of X → Type, we have a boundedness condition that we only allow the functions X → Type which are set-theoretically inside . But which objects of Type 1 should we allow? In particular, consider the following set-theoretical function , take , if , return , otherwise return . If we allow to be in my model of functions g : Type → Type : Type 1, I have a problem, because I can have a function emb : X → Type which is modeled just by a set-theoretical inclusion, and should be safely inside the model, and can obtain back the problematic f := g ∘ emb : X → Type. Sure, the function is a bit crazy, and should not be allowed but I don't see a good general rule for constructing Pi objects of Type 1.
Mirek Olšák (Dec 02 2025 at 10:35):
For example, for functions Type → Type it is still doable, there I consider only such functions , so that there exists a function such that for every , and , if , then . I have some ideas how to continue but it is unclear if it can generally work.
Mario Carneiro (Dec 02 2025 at 10:36):
I'm currently reading Luo's thesis on ECC and I think chapter 7 has what you want
Mario Carneiro (Dec 02 2025 at 10:56):
Oh, never mind, chapter 7 uses inaccessible cardinals in the end and the extra realizers are just used to provide a computational interpretation. I think the reason it is cited in Barras (referenced by Bas above) is because of chapter 6, which is a fully syntactic proof of consistency based on strong normalization. You can use that to construct a model but it won't have "the obvious" semantics for function types
Mirek Olšák (Dec 02 2025 at 21:53):
Actually, I think you are right that just some HOL-like hierarchy can do this, so without recursion, it could fit inside $V_{\omage\cdot\omega}$. Only the higher universe I take, the more complex information I need to keep it all bounded. The type that could store how an element on universe level u at the l-th level of building HOL-functions can be bounded could be Limit u l defined by
def Limit : Nat → Nat → Type
| 0, 0 => Nat
| u, l+1 => Limit u l × (Limit u l → Limit u l)
| u+1, 0 => Limit u 0 × (Σ l, Limit u l)
Mirek Olšák (Dec 02 2025 at 21:55):
Which is interestingly almost the same as defining the STT hierarchy on its own, just shifted by one universe...
Mirek Olšák (Dec 02 2025 at 23:07):
Perhaps something along those lines. I imagine building a model out of all the Bounded Hierarchys.
def Hierarchy (u : Nat) (l : Nat) : Type := match u with
| 0 => Unit
| u+1 => aux (Σ l, Hierarchy u l) l
where aux (start : Type) : Nat → Type
| 0 => start
| l+1 => aux start l → aux start l
def Hierarchy.toFun {u l : Nat} (x : Hierarchy (u+1) (l+1)) : Hierarchy (u+1) l → Hierarchy (u+1) l := x
def Hierarchy.ofFun {u l : Nat} (f : Hierarchy (u+1) l → Hierarchy (u+1) l) : Hierarchy (u+1) (l+1) := f
def Hierarchy.liftLev1 {u l : Nat} (x : Hierarchy (u+1) l) : Hierarchy (u+1) (l+1) := fun _ ↦ x
def Hierarchy.liftLevel {u l1 l2 : Nat} (x : Hierarchy (u+1) l1) (h : l1 ≤ l2) : Hierarchy (u+1) l2 :=
if eq : l1 = l2 then eq ▸ x
else
match l2 with
| 0 => False.elim (by omega)
| l2+1 => (x.liftLevel (l2 := l2) (by omega)).liftLev1
def Hierarchy.bounds {u l : Nat} (bound : Hierarchy u l) (f : Hierarchy (u+1) l) : Prop
:= match u, l with
| 0, _ => True
| u+1, l+1 =>
∀ (xb : Hierarchy (u+1) l) (xf : Hierarchy (u+2) l),
xb.bounds xf → (bound.toFun xb).bounds (f.toFun xf)
| u+1, 0 =>
∃ (h : f.1 ≤ bound.1), bound.2.bounds (f.2.liftLevel h)
def Hierarchy.Bounded {u l : Nat} (x : Hierarchy u l) := match u with
| 0 => True
| u+1 => ∃ bound : Hierarchy u l, bound.bounds x ∧
bound.Bounded -- not sure if condition is necessary...
Mario Carneiro (Dec 02 2025 at 23:55):
I think the base of your hierarchy needs to be something other than Unit or else the whole hierarchy is unit types
Mario Carneiro (Dec 02 2025 at 23:55):
but I'm not sure how you are solving the dependent types problem
Mirek Olšák (Dec 02 2025 at 23:56):
The base should not matter too much, I insert natural numbers with the Sigma type.
Mario Carneiro (Dec 02 2025 at 23:56):
is the idea that each type is a subset of one of the hierarchy types?
Mario Carneiro (Dec 02 2025 at 23:57):
the base of the hierarchy needs to cover all of your constant types, as well as Prop
Mario Carneiro (Dec 02 2025 at 23:57):
I think the hierarchy step function needs to be A + (A -> A) rather than just A -> A
Mirek Olšák (Dec 02 2025 at 23:57):
Well yeah, it could be more convenient to use later, I just wanted to define something simple to start with.
Mirek Olšák (Dec 02 2025 at 23:58):
My original idea was also to use the A + (A -> A) but then I realized I can do this lift using constant functions.
Mirek Olšák (Dec 02 2025 at 23:58):
the lift A -> (A -> A)
Mirek Olšák (Dec 03 2025 at 00:01):
The universe Type u could correspond to {x : Hierarchy (u+2) 0 // x.Bounded}
Mario Carneiro (Dec 03 2025 at 00:01):
What is the point of Bounded?
Mirek Olšák (Dec 03 2025 at 00:02):
To restrict the possible functions in higher universes, so that I cannot build a cofinal sequence.
Mario Carneiro (Dec 03 2025 at 00:03):
do you have an example in mind?
Mario Carneiro (Dec 03 2025 at 00:03):
I'm trying to unpack the definition
Mirek Olšák (Dec 03 2025 at 00:03):
The issue I was explaining here:
Mario Carneiro (Dec 03 2025 at 00:04):
this seems more syntactic than that
Mirek Olšák (Dec 03 2025 at 00:04):
The idea is: I don't want to allow all functions Type -> Type.
Mirek Olšák (Dec 03 2025 at 00:05):
so for every function f : Type -> Type, I need a function bound : Nat -> Nat
Mario Carneiro (Dec 03 2025 at 00:06):
but bound isn't a Nat -> Nat, it's a Type u-1 -> Type u-1 IIUC
Mirek Olšák (Dec 03 2025 at 00:06):
well yes, it gets more complicated in higher universes :sweat_smile:
Mario Carneiro (Dec 03 2025 at 00:06):
okay so your case is for u=0?
Mirek Olšák (Dec 03 2025 at 00:07):
Otherwise, this hierarchy starts with Unit, Nat, and then something rich.
Mario Carneiro (Dec 03 2025 at 00:07):
Oh no, for u=0 Bounded is trivial
Mario Carneiro (Dec 03 2025 at 00:07):
so you allow Type -> Type to contain everything
Mario Carneiro (Dec 03 2025 at 00:08):
but only restrict it when used as an element of Type 1?
Mirek Olšák (Dec 03 2025 at 00:08):
The start is a bit random, I imagine Type to be Hierarchy 2 0
Mirek Olšák (Dec 03 2025 at 00:09):
Hierarchy 0 0 is just dummy Unit, Hierarchy 1 0 is Nat
Mario Carneiro (Dec 03 2025 at 00:09):
okay so you want x : Hierarchy 2 0 which is bounded by some bound : (Hierarchy 1 0 := Nat)
Mario Carneiro (Dec 03 2025 at 00:12):
Unraveling the definition of bounds I don't see why it's not just trivially true in this case
Mario Carneiro (Dec 03 2025 at 00:12):
maybe it is?
Mirek Olšák (Dec 03 2025 at 00:12):
Every x : Hierarchy 2 0 is still trivially Bounded by something but the bound is not constant.
Mirek Olšák (Dec 03 2025 at 00:13):
So not every function f : Hierarchy 2 1 is Bounded.
Mirek Olšák (Dec 03 2025 at 00:16):
I will write you an example of unbounded function
Mario Carneiro (Dec 03 2025 at 00:17):
so this is a function Hierarchy 2 0 -> Hierarchy 2 0, the identity function is presumably not bounded
Mirek Olšák (Dec 03 2025 at 00:17):
Identity should be bounded by identity
Mario Carneiro (Dec 03 2025 at 00:18):
oh because the bound is Hierarchy 1 1
Mario Carneiro (Dec 03 2025 at 00:18):
why is the bound not Hierarchy 1 0?
Mirek Olšák (Dec 03 2025 at 00:18):
The idea is that it must be bounded by an "approximation" Nat -> Nat
Mirek Olšák (Dec 03 2025 at 00:19):
Because the identity function should exist in my type system
Mirek Olšák (Dec 03 2025 at 00:28):
This should be an unbounded example
-- not a relevant definition, just something of that type
def something {l : Nat} : Hierarchy 1 l := (id ⟨0, ()⟩ : Hierarchy 1 0).liftLevel (Nat.zero_le l)
def unboundedExample : Hierarchy 2 1 := .ofFun fun x =>
let ⟨l, x1⟩ := x
match l with
| 0 => ⟨x1.1, something⟩
| _+1 => x
But it is true that I haven't thought much yet how to represent sets...
Mirek Olšák (Dec 03 2025 at 00:30):
The idea is that it takes the bottom level of Hierarchy 2 0, and maps it to a sequence spanning all the levels.
Mario Carneiro (Dec 03 2025 at 00:39):
theorem unbounded (bound : Hierarchy 1 1) : ¬ bound.bounds unboundedExample := by
open Hierarchy in
intro H
unfold bounds at H
replace H n := H ⟨0, ()⟩ ⟨0, n, ()⟩ <| by simp [bounds]
simp [unboundedExample, bounds, Hierarchy.ofFun, Hierarchy.toFun] at H
exact Nat.not_succ_le_self _ (H ((bound ⟨0, ()⟩).1 + 1))
Last updated: Dec 20 2025 at 21:32 UTC