Zulip Chat Archive
Stream: new members
Topic: Simple Type Class Synthesis Failure
Zach (Sep 19 2025 at 18:44):
I have a proof which is mysteriously (to me) failing to synthesize a type class instance. I've distilled the issue into a simple example:
section
variable {T : Type}
variable [BEq T]
variable [EquivBEq T]
-- failed to synthesize PartialEquivBEq (Option T)
#synth PartialEquivBEq (Option T)
Because EquivBEq T implies PartialEquivBEq T (right?), I'm surprised that we can't synthesize PartialEquivBEq (Option T). I've been able to synthesize PartialEquivBEq (Option ...) in other examples and even adding variable [PartialEquivBEq T] to the above doesn't correct the problem. Is there a good way to diagnose why a type class instance can't be synthesized or what steps Lean attempted to take to synthesize it?
Robin Arnez (Sep 19 2025 at 18:46):
Well, there is no EquivBEq instance for Option. In other cases it presumably went through LawfulBEq
Zach (Sep 19 2025 at 18:48):
I see; thanks! Is there a way for me to ask lean how it has synthesized a type class instance so I can see this line of reasoning?
Robin Arnez (Sep 19 2025 at 19:04):
Well, for one you can recursively hover over the output of #synth to see which instances it used. If you want to know how it got the answer you can also use set_option trace.Meta.synthInstance true in above the #synth
Zach (Sep 19 2025 at 19:16):
Thanks again! This is helpful. It hadn't occurred to me that the solution to my other tests was via LawfulBEq. I'm trying to write some proofs generally enough that == could over-equate things (e.g. two sets represented as lists could use == to canonicalize). Perhaps that's against the grain of how I'm expected to work.
I'm a little surprised that there's no PartialEquivBEq for Option, but I'm guessing that's just because not everything can be in the standard library. The upside is that I can declare my own instance if I want:
instance {T : Type} [BEq T] [PartialEquivBEq T]
: PartialEquivBEq (Option T) where
symm := by
intro a b H
cases a <;> cases b <;> try simp_all
case some.some a' b' =>
apply PartialEquivBEq.symm
exact H
trans := by
intro a b c H1 H2
cases a <;> cases b <;> cases c <;> try simp_all
case some.some.some a' b' c' =>
exact PartialEquivBEq.trans H1 H2
Thanks for the help!
Last updated: Dec 20 2025 at 21:32 UTC