Zulip Chat Archive
Stream: lean4
Topic: Odd type class failure
Tomas Skrivan (Dec 12 2021 at 19:16):
I have encountered this odd type class synthesis failure. I do not even know how to describe it, but it is an odd mix of reducible definition and a class in the assumption of another class
structure Foo where
α : Type u
class Bar' (X : Type) (S : Foo) extends Add X where
class Bar (X : Type) (S : Foo) [Add S.α] extends Add X where
abbrev foo : Foo := ⟨Nat⟩
def foo' : Foo := ⟨Nat⟩
instance : Add foo'.α := instAddNat
example (X) [Bar' X foo] : Add X := by infer_instance -- works
example (X) [Bar X foo'] : Add X := by infer_instance -- works
example (X) [Bar X foo] : Add X := by infer_instance -- fails
example (X) [Bar X foo] : Add X := Bar.toAdd foo -- works
Anyone has any idea why is example (X) [Bar X foo] : Add X := by infer_instance failing to synthesize an instance?
Sebastian Reichelt (Dec 12 2021 at 19:43):
Looks like Lean doesn't see the two occurrences of ⟨Nat⟩ as the same. It works if you change foo like this.
def foo' : Foo := ⟨Nat⟩
abbrev foo : Foo := foo'
The error is still strange IMHO.
Sebastian Reichelt (Dec 12 2021 at 19:48):
Oh, it works if S is an outParam:
structure Foo where
α : Type u
class Bar' (X : Type) (S : outParam Foo) extends Add X where
class Bar (X : Type) (S : outParam Foo) [outParam (Add S.α)] extends Add X where
abbrev foo : Foo := ⟨Nat⟩
def foo' : Foo := ⟨Nat⟩
instance : Add foo'.α := instAddNat
example (X) [Bar' X foo] : Add X := by infer_instance -- works
example (X) [Bar X foo'] : Add X := by infer_instance -- works
example (X) [Bar X foo] : Add X := by infer_instance -- works
example (X) [Bar X foo] : Add X := Bar.toAdd -- works
Tomas Skrivan (Dec 12 2021 at 19:55):
Sebastian Reichelt said:
Looks like Lean doesn't see the two occurrences of
⟨Nat⟩as the same. It works if you changefoolike this.def foo' : Foo := ⟨Nat⟩ abbrev foo : Foo := foo'The error is still strange IMHO.
Sure, but that way foo.1 is not Nat but foo'.1 and defeats the whole purpose why foo is abbrev.
Tomas Skrivan (Dec 12 2021 at 19:56):
Oh, it works if
Sis anoutParam
Interesting, what is going on there?
Tomas Skrivan (Dec 12 2021 at 19:58):
Another solution is to add: instance {X a} [Add a] [Bar X ⟨a⟩] : Add X := Bar.toAdd ⟨a⟩
Sebastian Reichelt (Dec 12 2021 at 20:11):
I hope someone more knowledgeable will chime in, but roughly speaking if you have an instance of Bar X foo in your context and want to synthesize Add X, Lean needs to infer the argument foo. Making the parameter an outParam causes it to always be inferred.
One important piece of the puzzle may be this: [Bar X foo] with Bar X foo extending Add X doesn't act like having [Add X] in your context. Instead, the instance of Add X is found by type class search, so first of all Bar X foo needs to be found in that particular call to infer_instance.
Mac (Dec 12 2021 at 20:11):
Tomas Skrivan said:
Oh, it works if
Sis anoutParamInteresting, what is going on there?
Without outParam on [Add S.α], it is a normal parameter of the the typeclass. That is, Bar is polymorphic in Add (S.α).
Last updated: May 02 2025 at 03:31 UTC