Zulip Chat Archive
Stream: general
Topic: Church numeral subtraction
Bob Rubbens (Oct 06 2025 at 06:51):
Hi all, I'm trying to define subtraction with church numerals in lean 4. I've come up with the following:
import Mathlib.Data.Nat.Notation
def ChurchNat.{u} := (α : Type u) → (α → α) → α → α
def succ : ChurchNat → ChurchNat :=
fun n => fun α =>
fun f a => f (n α f a)
def succ_hist : ChurchNat × ChurchNat → ChurchNat × ChurchNat
| (m, _m_pred) => (succ m, m)
def pred (c : ChurchNat) : ChurchNat :=
(c (ChurchNat × ChurchNat) succ_hist (/- error at this c -/ c, c)).snd
I get an error on the marked c:
Application type mismatch: The argument
c
has type
ChurchNat.{?u.200 + 1}
of sort `Type (?u.200 + 2)` but is expected to have type
ChurchNat.{?u.200}
of sort `Type (?u.200 + 1)` in the application
Prod.mk c
Intuitively I understand why this is a problem: I'm applying c to itself here, and possibly, c is sercetly a y-combinator, meaning the resulting term would not terminate if executed, so the type system is preventing me from doing this. My questions are:
- Can I change my pred definition to make this typecheck? I tried adding a universe explicitly, but that didn't help, and I'm not experienced enough to know what more I can do.
- Should I maybe change my
ChurchNatdefinition to make this typecheck? - Or should I use the alternate definition for subtraction from wikipedia? I've heard that that one does typecheck, but I find it a lot harder to understand than this one, so I'm not so confident since I can't even get this one to typecheck. I prefer using one that I do understand, but if it cannot be made to work then I can obviously try something else.
- Or is this definition simply not type-checkable because of some other property of church numerals? Maybe someone else has written about this so I can learn?
Any helpful pointers are appreciated!
Kenny Lau (Oct 06 2025 at 09:10):
@Bob Rubbens you're getting "universe issue"'d. add universes to see the problem explicitly:
import Mathlib.Data.Nat.Notation
universe u
def ChurchNat : Type (u+1) := (α : Type u) → (α → α) → α → α
def succ : ChurchNat.{u} → ChurchNat.{u} :=
fun n => fun α =>
fun f a => f (n α f a)
def succ_hist : ChurchNat.{u} × ChurchNat.{u} → ChurchNat.{u} × ChurchNat.{u}
| (m, _m_pred) => (succ m, m)
def pred (c : ChurchNat.{u+1}) : ChurchNat.{u+1} :=
(c (ChurchNat.{u} × ChurchNat.{u}) succ_hist.{u} (/- error at this c -/ c, c)).snd
Kenny Lau (Oct 06 2025 at 09:10):
you're trying to apply c to c and there's no universe where you can do that
Bob Rubbens (Oct 06 2025 at 09:50):
Ok, so the only option is to try the formulation of pred as described on wikipedia. Too bad! I liked the pair-based formulation.
Alexander Bentkamp (Oct 06 2025 at 09:50):
Maybe you meant to write:
def pred (c : ChurchNat) : ChurchNat :=
(c (ChurchNat × ChurchNat) succ_hist (fun _ _ x => x, fun _ _ x => x)).snd
?
Bob Rubbens (Oct 06 2025 at 09:54):
Wow, I see what you mean. I have no clue how that typo snuck in there, but that's definitely on me. Already in notes going back some time when I started playing with this I make the mistake of not starting with zero... Thanks!
Last updated: Dec 20 2025 at 21:32 UTC