Zulip Chat Archive
Stream: mathlib4
Topic: TypePow
Kenny Lau (Jun 14 2025 at 16:54):
abbrev TypePow (α : Type u) : Nat → Type u
| 0 => PUnit
| 1 => α
| (n+1) => α × TypePow α n
example {α : Type u} : TypePow α 3 = (α × α × α) := rfl
#check ((3, 4, 5) : TypePow Nat 3)
Kenny Lau (Jun 14 2025 at 16:54):
In #maths > Projective Space I briefly touched on the possibility of having type power. What do yall think? Would this be a good idea to replace the current idiom Fin n -> R?
Kevin Buzzard (Jun 14 2025 at 16:58):
IIRC we had this in LTE but it was filed under "hacks".
Kenny Lau (Jun 14 2025 at 17:00):
The advantage of this is that this would enable us to reason about R^n while not sacrificing usability for low-dimension cases. For example, we can prove that each R^n is a module, but we can still construct explicit elements of R^3.
Kenny Lau (Jun 14 2025 at 17:01):
what is LTE?
Aaron Liu (Jun 14 2025 at 17:02):
Kenny Lau said:
The advantage of this is that this would enable us to reason about
R^nwhile not sacrificing usability for low-dimension cases. For example, we can prove that eachR^nis a module, but we can still construct explicit elements ofR^3.
We can also construct elements of Fin n → ℝ with the vector notation
Kenny Lau (Jun 14 2025 at 17:04):
@Aaron Liu This is after @David Ang discovered that R × R × R is better behaved than Fin 3 -> R and it makes more things defeq, and he has an open PR doing that refactor on elliptic curves. He is probably in a better position than me to explain why R × R × R is better.
Aaron Liu (Jun 14 2025 at 17:05):
Well I guess there's the eta unfolding but I don't see anything else right now
David Ang (Jun 14 2025 at 17:07):
My justification is in #maths > thoughts on elliptic curves @ 💬.
Aaron Liu (Jun 14 2025 at 17:08):
that link is broken nvm you fixed it
David Ang (Jun 14 2025 at 17:08):
Yeah I just realised all my old links to Zulip posts are broken (sorry Kenny! I'm fixing them now)
Kevin Buzzard (Jun 14 2025 at 17:17):
LTE is this https://github.com/leanprover-community/lean-liquid/blob/master/src/hacks_and_tricks/type_pow.lean but I am wrong -- it seems that we just used Fin n -> X.
Kenny Lau (Jun 14 2025 at 17:45):
David Ang said:
My justification is in #maths > thoughts on elliptic curves @ 💬.
I like how nobody in that thread has even thought about my proposed solution
David Ang (Jun 14 2025 at 17:47):
Would be nice if we have the abbrev .thd for your solution :)
Kenny Lau (Jun 14 2025 at 17:48):
@David Ang I tried to read the thread, I saw you said that this causes a lot of theorems to need erw; would you have an example of that? I think it would be easier for me to contextualise the whole situation if I'm presented with a concrete example of what actually breaks without the defeq
Kenny Lau (Jun 14 2025 at 17:48):
David Ang said:
Would be nice if we have the abbrev
.thdfor your solution :)
for that, Johan's suggestion with 11 thumbs up is to define .x .y .z specialised for elliptic curves. is that a good idea?
David Ang (Jun 14 2025 at 17:49):
Yeah, that's what I have in #24593
David Ang (Jun 14 2025 at 17:53):
An example of erw that I removed is here but I don't remember if that was one of the annoying ones.
David Ang (Jun 14 2025 at 17:56):
In any case I argue that ![x, y, z] 2 and z should be equal in some strong sense (e.g. definitionally) and shouldn't need a bunch of Matrix.head/tail_cons rewrites
Eric Wieser (Jun 14 2025 at 18:05):
Wish granted?
import Mathlib
example {x y z : α} : ![x, y, z] 2 = z := rfl
Eric Wieser (Jun 14 2025 at 18:05):
There is even a dsimproc that performs the simplification
David Ang (Jun 14 2025 at 18:06):
Yeah I guess I don't just mean definitionally, but something that can be rewritten over (I don't remember what this is called)
Eric Wieser (Jun 14 2025 at 18:06):
docs#Matrix.cons_val is that "rewrite":
example {x y z ret : α} (h : ret = z) : ![x, y, z] 2 = ret := by
simp_rw [Matrix.cons_val]
exact h.symm
Aaron Liu (Jun 14 2025 at 18:07):
What kind of rewriting? I know for rw if the head symbols don't match it doesn't even try.
David Ang (Jun 14 2025 at 18:07):
Yes, that's precisely the thing I'm trying to avoid - it shouldn't need a rewrite at all
Eric Wieser (Jun 14 2025 at 18:08):
I think you're going to have to make a mwe to make your point
David Ang (Jun 14 2025 at 18:16):
I don't have time to make an MWE right now but it's embedded in the permalink to my PR above. But in general:
lemma fin3_def {R : Type} [CommRing R] (P : Fin 3 → R) : ![P 0, P 1, P 2] = P := by ext n; fin_cases n <;> rfl
lemma smul_fin3 {R : Type} [CommRing R] (P : Fin 3 → R) (u : R) : u • P = ![u * P 0, u * P 1, u * P 2] := by simp [← List.ofFn_inj]
These should be rfl in my opinion
Eric Wieser (Jun 14 2025 at 18:24):
Best I can do is
import Mathlib
lemma fin3_def {R : Type} [CommRing R] (P : Fin 3 → R) : ![P 0, P 1, P 2] = P :=
FinVec.etaExpand_eq _
lemma smul_fin3 {R : Type} [CommRing R] (P : Fin 3 → R) (u : R) : u • P = ![u * P 0, u * P 1, u * P 2] :=
FinVec.etaExpand_eq _ |>.symm
David Ang (Jun 14 2025 at 18:24):
My point is that with the product construction (at least for R x R x R), these are true by rfl
David Ang (Jun 14 2025 at 18:26):
So the issue is really with eta expansion not being a rfl, but I guess there's not much we can do there
Eric Wieser (Jun 14 2025 at 18:30):
It's not clear to me how this translates to needing erw
Eric Wieser (Jun 14 2025 at 18:30):
erw only helps when things are rfl but not with_reducible rfl
David Ang (Jun 14 2025 at 18:31):
Yeah definitely! I'm saying I don't have time to make an MWE because I have deadlines coming and referred you to my link, so I just gave the simplest thing I wanted to hold
Kenny Lau (Jun 14 2025 at 20:08):
import Mathlib
universe u
abbrev TypePow (α : Type u) : ℕ → Type u
| 0 => PUnit
| 1 => α
| (n+2) => α × TypePow α (n+1)
lemma typePow_succ {α n} : TypePow α (n+2) = (α × (TypePow α (n+1))) := rfl
#check fun α : Type u ↦ α ^ 3 -- check that it has not been defined
instance : Pow (Type u) ℕ :=
⟨TypePow⟩
example {α : Type u} : α ^ 3 = (α × α × α) := rfl
#check ((3, 4, 5) : ℕ ^ 3)
def TypePow.get {α : Type u} : {n : ℕ} → α ^ n → Fin n → α
| 0, _, i => i.elim0
| 1, x, _ => x
| (_+2), x, i => Fin.cases x.1 (get x.2) i
def test : ℕ ^ 3 := (3, 4, 5)
#eval test.get -- ![3, 4, 5]
#eval test.get 0 -- 3
#eval test.get 1 -- 4
#eval test.get 2 -- 5
def TypePow.smul {α : Type u} {β : Type v} [SMul α β] (r : α) : {n : ℕ} → β ^ n → β ^ n
| 0, _ => PUnit.unit
| 1, x => r • x
| (_+2), x => (r • x.1, smul r x.2)
instance (α : Type u) (β : Type v) [SMul α β] (n : ℕ) : SMul α (β ^ n) :=
⟨fun r x ↦ TypePow.smul r x⟩
example {α β : Type*} [SMul α β] (r : α) (x : β ^ 3) :
r • x = (r • TypePow.get x 0, r • x.get 1, r • x.get 2) :=
rfl
Kenny Lau (Jun 14 2025 at 20:08):
not sure if this is 100% desirable, maybe there's some implementation details
Kenny Lau (Jun 14 2025 at 20:11):
it definitely needs polishing, so let's steer the topic back to whether we want this in mathlib
Aaron Liu (Jun 14 2025 at 20:13):
well we already have docs#List.TProd
Kenny Lau (Jun 14 2025 at 20:14):
Aaron Liu said:
well we already have docs#List.TProd
that is not good, I specifically used three cases to make sure that α ^ 1 is defeq to α!
Eric Wieser (Jun 14 2025 at 20:17):
I think we could easily change TProd to do the same thing, but it's not clear to me that there's any motivation for this defeq
Kenny Lau (Jun 14 2025 at 20:20):
Eric Wieser said:
I think we could easily change TProd to do the same thing, but it's not clear to me that there's any motivation for this defeq
so that you can write ((3, 4, 5) : ℕ ^ 3)
Last updated: Dec 20 2025 at 21:32 UTC