Zulip Chat Archive

Stream: lean4

Topic: I can't use an implicit argument. What else can I do?


Mitchell Lee (Mar 10 2024 at 08:39):

I am currently working on the theory of Coxeter groups. The specifics aren't important; what's important is that for every matrix M : Matrix B B ℕ, we have a group CoxeterGroup M. I have also defined a function wordProd that takes as input a List B and outputs an element of CoxeterGroup M; see below.

import Mathlib.Data.Matrix.Notation
import Mathlib.GroupTheory.PresentedGroup
import Mathlib.GroupTheory.SpecificGroups.Coxeter

namespace CoxeterGroup

open List Matrix
variable {B : Type*} [DecidableEq B]
variable (M : Matrix B B )

def simpleReflection (i : B) : CoxeterGroup M := PresentedGroup.of i
def wordProd (ω : List B) : CoxeterGroup M := prod (map (simpleReflection M) ω)

@[simp] theorem wordProd_append (ω ω' : List B) :
    wordProd M (ω ++ ω') = (wordProd M ω) * (wordProd M ω') := by
  sorry

end CoxeterGroup

Now, let's say that I am planning to have many more theorems like wordProd_append in the same file. I don't want to type wordProd M ω every time I use the wordProd function; I would rather type something like wordProd ω or π ω or something similar. This should be fine because the matrix M is "staying the same" throughout the section.

(The equivalent in informally written mathematics would be something like "Fix a matrix M, and let π = π_M be the associated word product function". From then on, I could just write π and it would be understood to mean π_M.)

Normally, I would accomplish this by making the argument M implicit in wordProd. However, I can't do that here. The problem is that Lean does not have any way to infer the implicit argument, because the only other place that M appears in the signature of wordProd is in the return type.

What are my options?

Joël Riou (Mar 10 2024 at 14:49):

If M is declared as {M}, then you should be able to write wordProd ω : CoxeterGroup M or wordProd (M := M) ω (warning: untested). However, in this particular situation, instead of using the type CoxeterGroup M, I would suggest using cs : CoxeterSystem M W as a variable (and use dot notation, like cs.wordProd ...), so that the API applies not only to the group CoxeterGroup M but to any group W that is part of a Coxeter system.

Raghuram (Mar 10 2024 at 17:14):

Incidentally, (independent of the suggestion above) Lean 3 used to have a command just for this: parameter. I don't know whether any analogue has been implemented in Lean 4 / Mathlib4.

Kyle Miller (Mar 10 2024 at 17:25):

The only analogue is making a local notation, which works since local notations are allowed to refer to variables

Mitchell Lee (Mar 10 2024 at 19:43):

Thanks for the suggestions.

I have tried multiple ways to make the argument M implicit. I have gotten it to work by doing this:

import Mathlib.Data.Matrix.Notation
import Mathlib.GroupTheory.PresentedGroup
import Mathlib.GroupTheory.SpecificGroups.Coxeter

namespace CoxeterGroup

open List Matrix
variable {B : Type*} [DecidableEq B]
variable {M : Matrix B B }

def simpleReflection (i : B) : CoxeterGroup M := PresentedGroup.of i
def wordProd (ω : List B) : CoxeterGroup M := prod (map simpleReflection ω)

@[simp] theorem wordProd_append (ω ω' : List B) :
    wordProd (M := M) (ω ++ ω') = (wordProd (M := M) ω) * (wordProd (M := M) ω') := by
  sorry

end CoxeterGroup

I can do the same thing with a type annotation on each use of wordProd. But, of course, this is even more cumbersome than writing just writing wordProd M ω. Removing any one of the occurrences of (M := M)or any one of the type annotations yields an error message:

(deterministic) timeout at 'whnf', maximum number of heartbeats (200000) has been reached (use 'set_option maxHeartbeats <num>' to set the limit)

I don't know whether this is intended behavior.

The notation idea is working great, though. Thank you for the suggestion.

Mitchell Lee (Mar 10 2024 at 19:47):

Yes, it does seem like I really want something like parameter, though.


Last updated: May 02 2025 at 03:31 UTC