Zulip Chat Archive
Stream: mathlib4
Topic: recursive definitions in instance fields
Jireh Loreaux (Nov 21 2022 at 15:34):
In mathlib4#672 I seem to be stuck on an issue of how to construct something recursively with pattern matching. In Lean 3, it looks like this, and I have included the tactic state at the relevant place (note the _match
). In Lean 4, I had to add the extra arguments to match on, but I can't seem to refer recursively to the conn
function, where in Lean 3 we could do this with _match
.
Lean 3
Lean 4
Jireh Loreaux (Nov 21 2022 at 16:37):
FYI: asked this in the Lean 4 stream on a simplified example: https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/recursive.20definition.20in.20structure.20fields
Adam Topaz (Nov 21 2022 at 17:12):
You could use let rec
I suppose. I don't know if this is the best approach though
Jireh Loreaux (Nov 21 2022 at 17:19):
yeah, I thought of that as a last resort, but surely there is (or at least needs to be) a better way, especially because in that case I have to write down the full type.
Adam Topaz (Nov 21 2022 at 17:27):
I guess the following isn't too verbose:
theorem foo : ∀ n : Nat, 0 ≤ n
| 0 => Nat.le_refl 0
| n + 1 => Nat.le_trans (foo n) n.le_succ -- works
example : ∀ n : Nat, 0 ≤ n
| 0 => Nat.le_refl 0
| n + 1 => Nat.le_trans (_example n) n.le_succ -- works
structure Bar :=
bar : ∀ n : Nat, 0 ≤ n
def myBar : Bar where
bar :=
let rec aux
| 0 => Nat.le_refl 0
| n + 1 => Nat.le_trans (aux n) n.le_succ
aux
Adam Topaz (Nov 21 2022 at 17:27):
but I agree that there should be a better way to do this.
Jireh Loreaux (Nov 21 2022 at 17:30):
In this case it's not too verbose, but if Lean can't infer the type of aux
and it's relatively painful to write, then it gets silly.
Jireh Loreaux (Nov 21 2022 at 17:32):
That being said, it can infer the type in my situation as well.
Adam Topaz (Nov 21 2022 at 17:32):
Note that this works as well
theorem foo : ∀ n : Nat, 0 ≤ n
| 0 => Nat.le_refl 0
| n + 1 => Nat.le_trans (foo n) n.le_succ -- works
example : ∀ n : Nat, 0 ≤ n
| 0 => Nat.le_refl 0
| n + 1 => Nat.le_trans (_example n) n.le_succ -- works
structure Bar :=
bar : ∀ n : Nat, 0 ≤ n
def myBar : Bar where
bar := aux where
aux
| 0 => Nat.le_refl 0
| n + 1 => Nat.le_trans (aux n) n.le_succ
Adam Topaz (Nov 21 2022 at 17:34):
and I suppose that's better for the issue you brought up
Henrik Böving (Nov 21 2022 at 17:54):
Jireh Loreaux said:
In this case it's not too verbose, but if Lean can't infer the type of
aux
and it's relatively painful to write, then it gets silly.
shouldn't it always be able to infer the type given that it is used right afterwards as a value for a field where the type is known?
Jireh Loreaux (Nov 21 2022 at 17:55):
But doesn't it have to parse elaborate the let
binding first? I thought that's why Adam's second solution would be better in general.
Henrik Böving (Nov 21 2022 at 17:57):
Not necessarily, the elaboration procedure can always "yield" back to the next highe relaborator and let it do some more work before continuing with its own elaboration later on in hopes that more information (such as the type) might be available. While I am not sure that this is the case here it is very much a possiblity.
Henrik Böving (Nov 21 2022 at 17:59):
For example you can use sorry
in the let here:
def myBar : Bar where
bar :=
let rec aux := sorry
aux
in which case it is impossible for lean to derive the type of aux
just from looking at the value because sorry
already expects the type to be known so I would expect that this delayed elaboration (or some variation) is indeed what is happening here
Adam Topaz (Nov 21 2022 at 18:10):
Regardless, it seems pretty silly that
bar := aux where
aux ...
works but
bar ...
doesn't
Jireh Loreaux (Nov 21 2022 at 18:40):
ugh... this hack doesn't pass the defLemma
linter (and hence also it wants a docstring so it doesn't pass docBlame
either).
Jireh Loreaux (Nov 21 2022 at 18:49):
@Mario Carneiro I'm not sure how to proceed here.
Mario Carneiro (Nov 21 2022 at 18:51):
The use of _match
is a dirty hack in lean 3 to emulate let rec
Jireh Loreaux (Nov 21 2022 at 18:52):
okay, so do I just add nolint
s?
Mario Carneiro (Nov 21 2022 at 18:53):
what does the code look like?
Jireh Loreaux (Nov 21 2022 at 18:54):
see mathlib4#672, the instances of isOrderConnected
, isTrichotomous
and isAsymm
.
Mario Carneiro (Nov 21 2022 at 19:44):
this is fixed in lean4#1866, you can add these to the nolints file (not the nolint
attribute) until then
Last updated: Dec 20 2023 at 11:08 UTC