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