Zulip Chat Archive
Stream: general
Topic: Section variables + typeclasses + notations
Markus de Medeiros (Feb 09 2026 at 14:16):
I ran into a problem in Iris-Lean recently and I'm looking for a any ideas on how to structure the code better to fix it. Here is a minimized version of the problem:
Code
Basically, I want the (5 ↦[γ] "A") notation to refer to the ElemG and Fraction instances from the context, but Lean doesn't do this because GF and F are metavariables. In Rocq, the section variables for GF and F would be inserted into every definition in the section, meaning they are not metavariables, and the typeclass synthesis can proceed fine. I don't want to change my top-level notation to include GF and F.
The hack I came up with above works fine for this example, but I've noticed it doesn't work so well when I need multiples of the same typeclass (in our case, ElemG's). Is there a better way?
Shreyas Srinivas (Feb 09 2026 at 14:36):
Here's a hack:
axiom BundledGFunctors : Type _
axiom GName : Type _
axiom GFunctor : Type _
class Fraction (F : Type _)
axiom F1 [Fraction F] : GFunctor
class ElemG (GF : BundledGFunctors) (F : GFunctor)
axiom IProp (GF : BundledGFunctors) : Type _
axiom points_to {GF : BundledGFunctors} [Fraction F] [ElemG GF (F1 (F := F))] : GName → Nat → String → IProp GF
axiom entails {GF : BundledGFunctors} : IProp GF → Prop
noncomputable section Example2
variable {F} [i₁ : Fraction F] {GF} [i₂ : ElemG GF (F1 (F := F))]
def MyPointsTo (γ : GName) (n : Nat) (s : String) := @points_to F GF _ _ γ n s
set_option quotPrecheck false in
notation k:50 " ↦[" γ:50 "] " v:50 => @points_to F GF i₁ i₂ γ k v
example {γ : GName} : entails (5 ↦[γ] "A") := sorry
-- no more typeclass stuck problems
end Example2
Shreyas Srinivas (Feb 09 2026 at 14:36):
Now it works
Shreyas Srinivas (Feb 09 2026 at 14:37):
Just force lean to use a specific typeclass instance (which you declare as a variable) explicitly
Shreyas Srinivas (Feb 09 2026 at 14:38):
So one thing lean is annoying about is, inside notation, it considers variable declarations unhygienic. So I temporarily disable quotPrecheck just for that notation, because I don't expect to get that wrong.
Markus de Medeiros (Feb 09 2026 at 14:43):
Ah interesting, thanks!
Shreyas Srinivas (Feb 09 2026 at 14:45):
another related dirty trick I use sometimes is simp [explicitInstanceName] to get around these typeclass unification issues instead of simp[TypeclassName.<something>] (the simp is just illustrative). This is handy when there are multiple instances of the same typeclass or different typeclasses in the same hierarchy using the same notation (which happens a lot when you mix TCS and mathlib's order theory).
Shreyas Srinivas (Feb 09 2026 at 14:57):
@Markus de Medeiros : Actually I think this specific instance of the problem has nothing to do with typeclass inference
axiom BundledGFunctors : Type _
axiom GName : Type _
axiom GFunctor : Type _
class Fraction (F : Type _)
axiom F1 [Fraction F] : GFunctor
class ElemG (GF : BundledGFunctors) (F : GFunctor)
axiom IProp (GF : BundledGFunctors) : Type _
axiom points_to {GF : BundledGFunctors} [Fraction F] [ElemG GF (F1 (F := F))] : GName → Nat → String → IProp GF
axiom entails {GF : BundledGFunctors} : IProp GF → Prop
noncomputable section Example2
variable {F} [i₁ : Fraction F] {GF} [i₂ : ElemG GF (F1 (F := F))]
def MyPointsTo (γ : GName) (n : Nat) (s : String) := @points_to F GF _ _ γ n s
set_option quotPrecheck false in
notation k:50 " ↦[" γ:50 "] " v:50 => @points_to F GF _ _ γ k v
example {γ : GName} : entails (5 ↦[γ] "A") := sorry
-- no more typeclass stuck problems
end Example2
Shreyas Srinivas (Feb 09 2026 at 14:57):
It seems to be entirely a problem caused by name hygiene in notation. Otherwise how would inference succeed for _ and _ in the above example?
EDIT : I think unnamed typeclass instances are being treated as metavars in the notation. Named typeclass variables are being inferred even if I only give an _ where I want the instance. Try deleting i₁ : and my solution doesn't work.
Shreyas Srinivas (Feb 09 2026 at 15:04):
I am mildly confused why adding a name to the instance matters, and would like to figure what's really happening beyond my guesswork. Time to call Batman.
CC : @Mario Carneiro
Sebastian Ullrich (Feb 09 2026 at 15:23):
Shreyas Srinivas said:
inside notation, it considers
variabledeclarations unhygienic
Which of course is exactly right in global notations. So the correct fix is to make them local notation
Shreyas Srinivas (Feb 09 2026 at 15:30):
Interesting. The warning messages I have received so far suggest the set_option quotPrecheck false solution, so I never figured local notation would do the trick
Shreyas Srinivas (Feb 09 2026 at 18:05):
@Sebastian Ullrich : why does it make a difference whether or not I name the typeclass instance in my final example?
Sebastian Ullrich (Feb 09 2026 at 18:06):
I don't see that on live
Shreyas Srinivas (Feb 09 2026 at 18:28):
I got an error when I removed the name i1
Shreyas Srinivas (Feb 09 2026 at 18:29):
Can’t seem to get it now.
Last updated: Feb 28 2026 at 14:05 UTC