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 changefoo
like 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
S
is 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
S
is anoutParam
Interesting, 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: Dec 20 2023 at 11:08 UTC