Zulip Chat Archive

Stream: lean4

Topic: possible parsing bug: invalid {...} notation


Alexander Bentkamp (Dec 17 2025 at 11:48):

Is this a bug in the parser?

----- Works:
class A

class B
  where
  lt (a : Nat) [A] : Bool

instance : B where
  lt (a : Nat) [A] := true

----- Does not work:
class X

class Y
  where
  lt [X] : Bool

instance : Y where
  lt [X] := true
-- invalid {...} notation, exactly one explicit source is required when using '[<index>] := <value>' update notation

Damiano Testa (Dec 17 2025 at 12:24):

Assuming that I understood what you want, it "works" with curly brackets:

instance : Y where
  lt {a} := true

Damiano Testa (Dec 17 2025 at 12:25):

(or nothing at all!)

Alexander Bentkamp (Dec 17 2025 at 12:28):

Another workaround I found:

instance : Y where
  lt := fun [X] => true

Damiano Testa (Dec 17 2025 at 12:29):

My second comment was very cryptic: this also works

instance : Y where
  lt := true

Alexander Bentkamp (Dec 17 2025 at 12:29):

I got it, thanks!

Damiano Testa (Dec 17 2025 at 12:29):

You can see that the typeclass assumption is auto-introduced here.

Damiano Testa (Dec 17 2025 at 12:30):

I think that there is a lot of matching and assignment that it would be nice to have in that position, but not much is actually implemented (EDIT: or feasible).

Alexander Bentkamp (Dec 17 2025 at 12:31):

So, yeah, in practice this is unlikely to be a real issue. Still, the behavior is inconsistent and probably not intended.

Alexander Bentkamp (Dec 17 2025 at 12:31):

Anyway, I am happy with the workarounds you and I found.

Damiano Testa (Dec 17 2025 at 12:32):

At the very least, the error message could be more explicit about what the issue is, I think.

Kyle Miller (Dec 17 2025 at 15:57):

It's not a bug exactly, but a complication from structure notation. The where ... syntax is essentially a macro for := { ... }, and in { ... } you can use [...] to update array-like fields (internally called a "modifyOp"), like in

structure S where
  xs : Array Nat

def S.change0 (s : S) (x : Nat) : S := { s with xs[0] := x }

It only works with with though, which isn't present in where syntax, so the restriction is a little pointless here.

Something that is a little counterintuitive is that in where/{...} notation, the binder lists are effectively fun binder lists. The binder list here comes from the expected type, so all you need to do is provide identifiers, not (...)/[...]/{...}/{{...}} brackets. In this case, since the X parameter is implicit, it's automatically introduced anyway:

instance : Y where
  lt := true

Damiano already pointed this one out, but this is the reason for not needing to mention the parameter at all.

Kyle Miller (Dec 17 2025 at 15:58):

(One way this could be improved is to put noWs into the modifyOp parser. There's no reason to accept xs [0] := x.)

Damiano Testa (Dec 17 2025 at 16:02):

Oh, I did not realise that the error message was coming from a modifyOp!


Last updated: Dec 20 2025 at 21:32 UTC