Zulip Chat Archive
Stream: new members
Topic: 3 incorrectly accepted as Fin 1?
aron (May 31 2025 at 14:40):
I've got a type that contains type indices n : Nat and a Fin n:
inductive Ctx (α : Type u) : (n : Nat) → Type u
| nil : Ctx α 0
| add {n} (body : Ctx α n) (tip : α) : Ctx α (n+1)
inductive HasType {α : Type u} : (n : Nat) → (index : Fin n) → Ctx α n → α → Type u where
| stop : HasType 1 3 (Ctx.add Ctx.nil ty) ty -- <-- 3 works here?
| pop : HasType n fin ctx ty → HasType (n+1) fin.succ (Ctx.add ctx otherTy) ty
In the stop constructor it looks like lean has no problem with me setting the Fin n to a value of 3, even though obviously 3 < 1 is false.
This also works when I do ⟨ 3, _ ⟩. Although when I do ⟨ 3, by sorry ⟩ it clearly shows that the goal is 3 < 1. So why does this work? Is this a bug?
Jz Pan (May 31 2025 at 14:46):
It wraps around.
aron (May 31 2025 at 14:47):
Sorry what does that mean?
Etienne Marion (May 31 2025 at 14:49):
It comes from this: Fin.ofNat'. It uses 3 % n.
Yaël Dillies (May 31 2025 at 14:49):
3 : Fin 1 means ⟨3 % 1, (some_proof : 3 % 1 < 1)⟩ : Fin 1
Yaël Dillies (May 31 2025 at 14:49):
In particular, (3 : Fin 1) = (0 : Fin 1)
aron (May 31 2025 at 14:49):
oh. that seems.. unexpected.
aron (May 31 2025 at 14:50):
:neutral:
Robin Arnez (May 31 2025 at 14:55):
Well it's because Fin n is meant to model a modular ring with addition, subtraction and multiplication and in particular it is also the basis for UInt8 etc. which have similar behavior.
aron (May 31 2025 at 14:56):
:neutral:
:expressionless:
:neutral:
Kevin Buzzard (Jun 01 2025 at 00:44):
Someone should be making a list of everyone who is caught out by this clearly unexpected behaviour
Matt Diamond (Jun 01 2025 at 01:43):
I thought ZMod was meant to model a modular ring... maybe Fin should be more strict while ZMod continues with the existing behavior
Jireh Loreaux (Jun 01 2025 at 02:44):
This OfNat is in core, as are the arithmetic instances. I don't think they're changing. Moreover, I've never seen another suggestion for behavior that makes more sense / is better.
If you want a Fin with different arithmetic, create a type synonym.
Yaël Dillies (Jun 01 2025 at 05:33):
Here's a concrete suggestion: If you want to verify that index i : ℕ isn't out of bounds, do ⟨i, some_proof⟩ : Fin n, rather than i : Fin n.
Yaël Dillies (Jul 10 2025 at 16:53):
For anyone coming here from the future, the ℕ → Fin n coercion was removed from Lean core in lean#8620, and in mathlib docs#Fin.instCommRing isn't an instance either anymore.
Last updated: Dec 20 2025 at 21:32 UTC