Zulip Chat Archive

Stream: Is there code for X?

Topic: (2, 3, 5).3


Kenny Lau (Oct 24 2025 at 01:57):

so i was too bored so i made f.3 work where f : Nat × Nat × Nat (the title is clickbait because it doesn't actually work with explicit Prod.mk, which i deemed there is no point in making it work because you would just write 5)

import Lean.MetavarContext
import Mathlib.Init

open Lean Meta Elab Term

-- this will fail for say (2, 3, 5, 7).4 because at that point there is no point
elab t:term"."n:num : term => do
  have n := n.getNat
  let t  elabTerm t none
  let e  inferType t
  let mut curr := e
  let mut s := 1
  while true do
    let m₁  mkFreshExprMVar none
    let m₂  mkFreshExprMVar none
    let u₁  mkFreshLevelMVar
    let u₂  mkFreshLevelMVar
    if  isDefEq (mkApp2 (mkConst ``Prod [u₁, u₂]) m₁ m₂) curr then
      let .some c'  getExprMVarAssignment? m₂.mvarId! | break
      curr := c'
      s := s + 1
    else break
  if s < 2  s < n then throwUnsupportedSyntax
  have e₁ : Expr := (n - 1).rec t fun _ ih  .proj ``Prod 1 ih
  have e₂ := if s = n then e₁ else .proj ``Prod 0 e₁
  return e₂

variable (f : Nat × Nat × Nat)

#check f.3

def foo := Nat × Nat × Nat

variable (g : foo)

#check g.1
#check g.2
#check g.3

Kenny Lau (Oct 24 2025 at 01:57):

and this implementation has the flaw that it makes g.1 and g.2 ambiguous (the first one is avoidable)

Kenny Lau (Oct 24 2025 at 01:58):

the second one can be worked-around by putting (g.2 : Nat)

Kenny Lau (Oct 24 2025 at 01:59):

or it can be fixed by changing the syntax to say g.get2

Kenny Lau (Oct 24 2025 at 01:59):

or some special hardcoding that only changes the syntax for g.2 (it's unfair to change the rest just to fit g.2)

Aaron Liu (Oct 24 2025 at 02:00):

I did this too

Aaron Liu (Oct 24 2025 at 02:00):

let me find it real quick

Kenny Lau (Oct 24 2025 at 02:00):

what was your solution to g.2?

Kenny Lau (Oct 24 2025 at 02:02):

aha i can change the syntax to g.%2

Kenny Lau (Oct 24 2025 at 02:02):

i think this is good

Aaron Liu (Oct 24 2025 at 02:02):

https://leanprover.zulipchat.com/#narrow/channel/116395-maths/topic/thoughts.20on.20elliptic.20curves/near/502148036

Aaron Liu (Oct 24 2025 at 02:02):

Kenny Lau said:

what was your solution to g.2?

no solution, unfortunately

Kenny Lau (Oct 24 2025 at 02:02):

ah your solution was g..2

Kenny Lau (Oct 24 2025 at 02:08):

@Damiano Testa on Aaron's linked thread you mentioned that it's not a good idea, and then if I click your link I see Mario's justification of this opinion that x.3 can mean both x.2.1 and x.2.2, which does not apply in this case; do you still hold this belief that this is bad in general?

Aaron Liu (Oct 24 2025 at 02:11):

The problem now is that x.2 can mean either x.2 or x.2.1 and this is the problem I have no good solution to

Kenny Lau (Oct 24 2025 at 02:12):

right, that's also a headache for me

Kenny Lau (Oct 24 2025 at 02:12):

my current workarounds would be either

  1. just disable this, only allow .$n for n>2
  2. or create special syntax just for 2, such as .%2 (but keep .3)
  3. or make special syntax in general, such as .%2 and .%3

Kenny Lau (Oct 24 2025 at 02:14):

but i don't think this .2 issue should just overrule the other .3 .4 .5 that would be useful

Aaron Liu (Oct 24 2025 at 02:15):

but now x.3 can mean x.2.2 or x.2.2.1

Aaron Liu (Oct 24 2025 at 02:16):

this isn't just a problem with 2

Kenny Lau (Oct 24 2025 at 02:16):

i don't see why this is a problem, it means different things depending on the type of x

Kenny Lau (Oct 24 2025 at 02:16):

unless we follow my polyvariable approach and enable say .x .y .z for "this file locally"

Kenny Lau (Oct 24 2025 at 02:17):

enable_prod_notation x y z

Aaron Liu (Oct 24 2025 at 02:17):

Kenny Lau said:

i don't see why this is a problem, it means different things depending on the type of x

It means specializing a free variable can change the meaning of the numbers

Kenny Lau (Oct 24 2025 at 02:19):

i see, that's a good point, but i think enable_prod_notation would solve this? at least for the elliptic curve case

Aaron Liu (Oct 24 2025 at 02:19):

oh I was thinking about more generality than just prod

Kenny Lau (Oct 24 2025 at 02:20):

i am aware of the limitations and have deliberately restricted to just Prod

Aaron Liu (Oct 24 2025 at 02:20):

if it's just prod and you already know how long it is it shouldn't be a problem

Kenny Lau (Oct 24 2025 at 02:33):

@Kim Morrison if you're here, i think you'd be interested in this thread, what's your opinion in using some sort of notation to hide away the x.2.2.2.1 thing that appears when one works with iterated Prod types?

Kenny Lau (Oct 24 2025 at 02:34):

https://github.com/search?q=repo%3Aleanprover-community%2Fmathlib4%20%22.2.2%22&type=code

Kenny Lau (Oct 24 2025 at 02:34):

maybe the real usecase is actually \and statements

Kenny Lau (Oct 24 2025 at 02:37):

image.png

Kim Morrison (Oct 24 2025 at 02:38):

I have been biting my tongue in this thread, as what I want to say is: "Kenny, you are so great at formalizing mathematics, please go and do that instead of introducing fragile and unhelpful notation, that fragments the ecosystem and increases maintenance burden."

Kenny Lau (Oct 24 2025 at 02:38):

i think one could make a very strong case for replacing these with .%3 and .%4...

Kim Morrison (Oct 24 2025 at 02:39):

i.e. I personally think this would be a net negative, even before counting the opportunity cost of you doing something useful. :-)

Kenny Lau (Oct 24 2025 at 02:41):

Kim Morrison said:

fragile

what if ... .%3 always elaborates to .2.2.1 and .%%3 will take the place of .2.2

Damiano Testa (Oct 24 2025 at 09:16):

Personally, I think that if you want .3 to work, then you should define your type to have (at least) 3 fields and let the third one by the one that you want to call .3.

Touching the way .n works, in the best of cases, leads to not being sure of what projection you are getting.


Last updated: Dec 20 2025 at 21:32 UTC