Zulip Chat Archive

Stream: lean4

Topic: Type equality up to beta-reduction


Clément Blaudeau (Sep 01 2025 at 13:12):

Hi! Sorry if it already answered somewhere. I have an error at typechecking, where Lean complains that some types foo and bar are not equal. Actually, they are up to beta-reduction. Consider this example:

example : Vector Bool 3 := Vector.replicate 3 true -- works fine
example : Vector Bool 3 := Vector.replicate (3: USize).toNat true -- fails

The latter fails with

type mismatch
  Vector.replicate (USize.toNat 3) true
has type
  Vector Bool (USize.toNat 3) : Type
but is expected to have type
  Vector Bool 3 : Type

Is there a way to have the typechecker "try a bit harder" to show type-equality, or give it a set of hints/tactics to use ? Or do I need to insert a coercion ?

[EDITED] added toNat

Patrick Massot (Sep 01 2025 at 13:19):

What makes you think USize and Nat are the same?

Patrick Massot (Sep 01 2025 at 13:20):

And which version of Lean are you using? The error message you quote is not what you get in the online playground.

Patrick Massot (Sep 01 2025 at 13:21):

By playground I mean following the link you see in the upper right corner of your code block, leading to https://live.lean-lang.org/#codez=KYDwhgtgDgNsAEAueA1YBjALgewE7wCFtsZ4BmJAXlQx1wDpdhYBLdMTBCzXAVwQC0A+AHc8AawDO8AGYsAdsABQoSLATI0WPIWKkKialrqNmMNhwQAKMsgCqAZRYAvYAEp4PfvCGywLGEklIA

Patrick Massot (Sep 01 2025 at 13:21):

which says:

Application type mismatch: The argument
  3
has type
  USize
but is expected to have type
  Nat
in the application
  Vector.replicate 3

Patrick Massot (Sep 01 2025 at 13:21):

which seems a very reasonable error message.

Patrick Massot (Sep 01 2025 at 13:23):

example : Vector Bool 3 := Vector.replicate ((3: USize).toNat) true also fails but indeed (3: USize).toNat doesn’t seem to be definitionally equal to 3 : Nat.

Clément Blaudeau (Sep 01 2025 at 13:26):

Yes indeed my minimized example was too minimized and missing a coercion from Usize to Nat.
The actual example is the one you've written:

example : Vector Bool 3 := Vector.replicate (3: USize).toNat true

How can I convince the typechecker that (3: Usize).toNat is 3 : Nat, at typechecking time ?

Clément Blaudeau (Sep 01 2025 at 13:27):

I've edited the first message to show the error I'm interested in

Robin Arnez (Sep 01 2025 at 13:30):

You'll need a cast:

example : Vector Bool 3 := (Vector.replicate (USize.toNat 3) true).cast (by simp)

The reason this doesn't work in the first place is because USize.toNat 3 is equivalent to 3 % 2 ^ System.Platform.numBits where System.Platform.numBits is an opaque system-dependent constant (i.e. they aren't definitionally equivalent and there's no way to force them to be). The solution here is to use a cast where you can use regular equality instead of definitional equality.

Patrick Massot (Sep 01 2025 at 13:31):

You can’t convince the type checking system that something is true by definition when it’s not.

Niels Voss (Sep 02 2025 at 20:50):

This seems to be a failure of canonicity (which states that every closed term of type Nat reduces to a normal form). Lean deliberately sacrifices canonicity for other properties deemed more important, so it should be expected that some things might fail, but I'm not sure why this particular example fails.

Aaron Liu (Sep 02 2025 at 20:51):

well you have opaque constants so

Aaron Liu (Sep 02 2025 at 20:52):

I certainly wouldn't want System.Platform.numBits to reduce to any numeral since it's system dependent

Aaron Liu (Sep 02 2025 at 20:52):

and USize wraps a BitVec System.Platform.numBits

Aaron Liu (Sep 02 2025 at 20:54):

Clément Blaudeau said:

How can I convince the typechecker that (3: Usize).toNat is 3 : Nat, at typechecking time ?

You add a docs#Vector.cast

Niels Voss (Sep 02 2025 at 21:00):

To be clear, I agree with Lean's decision to sacrifice canonicity


Last updated: Dec 20 2025 at 21:32 UTC