Zulip Chat Archive
Stream: lean4
Topic: Typechecking integers with graded things
Gareth Ma (Aug 20 2024 at 23:27):
So I have some graded objects, say GradedPapers
below:
structure GradedPapers (n : Int) where
grade : Int
def GradedPapers.combine {n : Int} (a : GradedPapers n) (b : GradedPapers n) : GradedPapers n :=
⟨a.grade + b.grade⟩
def PaperA : GradedPapers 3 := ⟨10⟩
def PaperB : GradedPapers (2 + 1) := ⟨10⟩
#check PaperA.combine PaperB
instance GradedPapers.instAdd {n : Int} : Add (GradedPapers n) := ⟨combine⟩
#check PaperA + PaperB
#check (PaperA + PaperB : GradedPapers 3)
def PaperB' : GradedPapers 3 := PaperB
def PaperAB : GradedPapers (1 + 1 + 1) := PaperA + PaperB'
The first check succeeds, while the last two fails, and the final definition succeeds (but not with PaperB
). I kind of understand why, but also not really, so I have some questions/clarifications:
- Since the first check succeeds, I believe
3
and2 + 1
are definitionally equal in the kernel/typechecker. Is that correct? - If so, why don't the second and third checks work?
- In fact, if I turn
set_option trace.Meta.synthInstance
on, I see the following:
[Meta.synthInstance] ✅ HAdd (GradedPapers 3) (GradedPapers 3) (GradedPapers 3) ▼
[Meta.synthInstance] ❌ HAdd (GradedPapers 3) (GradedPapers (2 + 1)) ?m.483 ▶
3a. Why doesn't it use the green tick line?? The output type is correct
3b. Why is the output type of the red cross line a hole (?m.483
)? It seems especially weird on the third check, because I explicitly wrote : GradedPapers 3
for the output type. Same for the PaperAB
if you replace PaperB'
by PaperB
.
- Is there any way to make
+
work smoothly here?
Gareth Ma (Aug 20 2024 at 23:27):
(There are questions hidden under the code block, please click "Show more" :D)
Eric Wieser (Aug 20 2024 at 23:56):
#check PaperA + (by exact PaperB)
work too!
Gareth Ma (Aug 21 2024 at 00:15):
Wow I hate it
Gareth Ma (Aug 21 2024 at 00:36):
Okay hmm but is there any other way? I think it's quite annoying if I have to write something like
import Mathlib.NumberTheory.ModularForms.EisensteinSeries.Basic
open EisensteinSeries ModularForm UpperHalfPlane CongruenceSubgroup
local notation "G[" k "]" => @eisensteinSeries_MF k 1 (by decide) 0
noncomputable def E₄ : ModularForm (Gamma 1) 4 := (1/2) • G[4]
noncomputable def E₆ : ModularForm (Gamma 1) 6 := (1/2) • G[6]
noncomputable def Δ : ModularForm (Gamma 1) 12 :=
(1/1728) • ((by exact (E₄.mul E₄).mul E₄) - (by exact E₆.mul E₆))
But if that's the best way for now, then sure.
Gareth Ma (Aug 21 2024 at 00:36):
But maybe it would be nice to have an extension of the (... : _)
syntax to really really force the type of the term (syntactically)
Yakov Pechersky (Aug 21 2024 at 01:25):
Can you make your 'combine' take two separate GradedPapers, one over n, one over m, and combine also takes a proof that n = m that is proven by autoparam omega or decide or something?
Gareth Ma (Aug 21 2024 at 12:06):
Okay I just tried, and (as always) the first check works, that's expected. But then I don't know how to define the Add
instance, so I changed it to a HAdd
instance, and now everything breaks down :(
import Mathlib.Tactic
structure GradedPapers (n : Int) where
grade : Int
set_option linter.unusedVariables false in
def GradedPapers.combine {n m : Int} (a : GradedPapers n) (b : GradedPapers m) (h' : n = m := by omega) :
GradedPapers n :=
⟨a.grade + b.grade⟩
def PaperA : GradedPapers 3 := ⟨10⟩
def PaperB : GradedPapers (2 + 1) := ⟨10⟩
#check PaperA.combine PaperB
-- instance GradedPapers.instAdd {n : Int} : Add (GradedPapers n) := ⟨combine⟩
instance GradedPapers.instHAdd {n : Int} {m : Int} [h : Fact (n = m)] :
HAdd (GradedPapers n) (GradedPapers m) (GradedPapers n) := ⟨fun x y ↦ combine x y h.out⟩
#check PaperA + PaperB
#check (PaperA + PaperB : GradedPapers 3)
def PaperB' : GradedPapers 3 := PaperB
def PaperAB : GradedPapers (1 + 1 + 1) := PaperA + PaperB'
Gareth Ma (Aug 21 2024 at 12:07):
(Small reminder that there's a "View in Playground" button)
Yakov Pechersky (Aug 21 2024 at 12:21):
Why Fact the equality? TC will never solve that
Gareth Ma (Aug 21 2024 at 12:24):
How should I do it then?
Yakov Pechersky (Aug 21 2024 at 12:24):
Under my omega proposal, you'd have notation based addition, not via a typeclass
Gareth Ma (Aug 21 2024 at 12:25):
What does that mean?
Gareth Ma (Aug 21 2024 at 12:25):
Oh like define a new notation+\_m
or something, then write that instead (M1 +\_m M2 +\_m M3
)?
Yakov Pechersky (Aug 21 2024 at 12:26):
Yakov Pechersky (Aug 21 2024 at 12:26):
Like the cycle notation is able to discharge the proof of nodup of the list
Yakov Pechersky (Aug 21 2024 at 12:27):
First show that your combine will work when calling combine explicitly on your 3 and 1+1+1 examples without having to provide a proof.
Gareth Ma (Aug 21 2024 at 12:28):
set_option quotPrecheck false in
notation A "+ₘ" B => GradedPapers.combine A B (by omega)
#check PaperA +ₘ PaperB
#check (PaperA +ₘ PaperB : GradedPapers 3)
def PaperAB : GradedPapers (1 + 1 + 1) := PaperA +ₘ PaperB
Okay I think this works perfectly - I think this is what you mean :thinking:
Gareth Ma (Aug 21 2024 at 12:28):
(all works)
Gareth Ma (Aug 21 2024 at 12:29):
In fact, using this I can remove the auto outParam for m = n
entirely
Yakov Pechersky (Aug 21 2024 at 12:29):
You could, or make it an implicit autoparam so that the notation doesn't even have to mention omega
Yakov Pechersky (Aug 21 2024 at 12:29):
Not sure if explicit vs implicit matters
Gareth Ma (Aug 21 2024 at 12:30):
structure GradedPapers (n : Int) where
grade : Int
set_option linter.unusedVariables false in
def GradedPapers.combine {n m : Int} (a : GradedPapers n) (b : GradedPapers n) {h' : n = m} :
GradedPapers n :=
⟨a.grade + b.grade⟩
def PaperA : GradedPapers 3 := ⟨10⟩
def PaperB : GradedPapers (2 + 1) := ⟨10⟩
#check PaperA.combine PaperB
set_option quotPrecheck false in
notation A "+ₘ" B => GradedPapers.combine A B (h' := by omega)
#check PaperA +ₘ PaperB
#check (PaperA +ₘ PaperB : GradedPapers 3)
def PaperAB : GradedPapers (1 + 1 + 1) := PaperA +ₘ PaperB
This seems to break, and I don't know why
Yakov Pechersky (Aug 21 2024 at 12:35):
When I said make it implicit, I meant implicit autoparam. It breaks now because your by omega in notation never fires on the h' argument
Yakov Pechersky (Aug 21 2024 at 12:35):
And you use n twice in arguments to combine
Gareth Ma (Aug 21 2024 at 12:35):
:man_facepalming: yes the second one is the issue
Gareth Ma (Aug 21 2024 at 12:36):
Thank you. I think I will stick with removing the h'
entirely for now, and when it breaks for whatever reason I can fall back to this
Gareth Ma (Aug 21 2024 at 12:38):
Also one more thing, is it possible to get dot notation to work in notation?
Gareth Ma (Aug 21 2024 at 12:41):
notation A "+ₘ" B => A.combine B
fails for some reason (the .combine
is treated as some metavariable I don't understand
Gareth Ma (Aug 21 2024 at 12:42):
Because I have two types of graded papers, both with an .add
, and it would be great to have the same notation for them
Gareth Ma (Aug 21 2024 at 12:56):
notation A "+ₘ" B => (A).combine B
works!
Last updated: May 02 2025 at 03:31 UTC