Zulip Chat Archive
Stream: lean4
Topic: structure with unassigned variable as default variable
David Renshaw (Jul 18 2022 at 19:43):
structure Foo :=
(x : Nat := 10) -- field of type `Nat` with default value `10`
(y : Nat := foobar) -- field of type `Nat` with default value `foobar` ... ?
#print Foo.mk
-- constructor Foo.mk : (x : Nat) → ({x : Type} → {foobar : Nat} → Nat) → Foo
David Renshaw (Jul 18 2022 at 19:44):
^ I'm trying to understand what's happening here.
David Renshaw (Jul 18 2022 at 19:44):
I expect the structure declaration to cause an error, because foobar
is an undeclared variable.
David Renshaw (Jul 18 2022 at 19:45):
Instead, it succeeds and apparently creates a field of type ({x : Type} → {foobar : Nat} → Nat)
Yakov Pechersky (Jul 18 2022 at 19:45):
I think it is doing implicit argument placement
Henrik Böving (Jul 18 2022 at 19:47):
First things first style wise we'd do:
structure Foo where
x : Nat := 10
y : Nat := foobar
in Lean 4, the foobar
is being treated as an implicit argument as Yakov suggested, and in order to accommodate that implicit variable Lean ends up creating quite an interesting type that you can see here. The eagerness of auto implicit has been subject to discussion before and there are some ideas around on how we could turn it down.
David Renshaw (Jul 18 2022 at 19:48):
I was also wondering about the difference between where
and :=
Sebastian Ullrich (Jul 18 2022 at 19:48):
No semantic difference
Henrik Böving (Jul 18 2022 at 19:49):
Maybe we should get rid off :=
for structures and classes at some point then to enforce the generally accepted style guide easier?
David Renshaw (Jul 18 2022 at 19:49):
I can maybe understand that foobar
is added as an autoimplicit, but what about the added {x : Type}
implicit parameter?
Henrik Böving (Jul 18 2022 at 19:51):
I'm not quite sure where it is pulling that one from either but its most likely a cause of the autoImplicit feature trying to do its job.
Sebastian Ullrich (Jul 18 2022 at 19:52):
Huh, that's strange
Sebastian Ullrich (Jul 18 2022 at 19:52):
In any case, I can't think of any reason to allow auto implicits in default values
Mac (Jul 18 2022 at 19:54):
Henrik Böving said:
Maybe we should get rid off
:=
for structures and classes at some point then to enforce the generally accepted style guide easier?
One use case of the :=
is in macros where constructing such a structure can be easier, but I am doubtful that would be a good enough reason to keep the alternative syntax around.
Mac (Jul 18 2022 at 19:59):
David Renshaw said:
about the added
{x : Type}
implicit parameter?
I imagine that is a by product of the interaction between auto implicits and the way default values for structures work. That is, the default value of a each field has invisible arguments corresponding to the values of the previous fields (e.g., x
) and I think the auto implicit mechanic has accidently lifted this invisible argument into a type while lifting foobar
(likely because the elimination procedure for x
failed because foobar
is a metavariable so it can not be sure if x
was used in foobar
until later when auto-implicits come in).
Henrik Böving (Jul 18 2022 at 20:01):
It is not the x
from the first parameter, if you name the first one different:
structure Foo where
lalala : Nat := 10
y : Nat := foobar
#check Foo.mk
you get
Foo.mk : Nat → ({x : Type} → {foobar : Nat} → Nat) → Foo
and it also happens if there is only a single field.
Mac (Jul 18 2022 at 20:02):
Ah, probably should have checked before commenting.
Mac (Jul 18 2022 at 20:05):
Interesting, the type is always one universe higher than that of the param:
structure Baz :=
(y : Type 2 := foobar)
#print Baz.mk
-- constructor Baz.mk : ({x : Type 3} → {foobar : Type 2} → Type 2) → Baz
Mac (Jul 18 2022 at 20:07):
Maybe it is the polymorphic type of foobar
before Lean narrows it to the type of the param?
Mac (Jul 18 2022 at 20:07):
Yep:
structure Bar :=
(y : Nat := (fun _ => 1) foobar)
#print Bar.mk
-- constructor Bar.mk.{u_1} : ({x : Sort u_1} → {foobar : x} → Nat) → Bar
Sebastian Ullrich (Jul 18 2022 at 21:21):
https://github.com/leanprover/lean4/pull/1320
James Gallicchio (Jul 18 2022 at 23:18):
Mac said:
One use case of the
:=
is in macros where constructing such a structure can be easier, but I am doubtful that would be a good enough reason to keep the alternative syntax around.
I use it in enough places in my codebase that it would be very annoying if we got rid of it. In particular I have a pattern like
class MyLargeClass (C : Type) where
field1 : type1
...
fieldn : typen
instance [OtherClass C] : Inhabited (MyLargeClass C) where
default := {
field1 := ...
...
fieldn := ...
}
-- In some other file
instance : MyLargeClass MyType := {
default with
field23 := ...
}
that is pretty nice, and only possible with the := syntax
Mac (Jul 19 2022 at 00:28):
@James Gallicchio I think the suggestion was just to remove :=
in structure
/ class
definitions, not elsewhere (e.g., in instance
). Thus, I should note that you did not use :=
in your class MyLargeClass
signature. ;)
James Gallicchio (Jul 19 2022 at 00:31):
Oh, oh, I see now. Reading is hard :)
Last updated: Dec 20 2023 at 11:08 UTC