Zulip Chat Archive
Stream: new members
Topic: Trying to define `LawfulBEq` instance
Ben Selfridge (Mar 22 2025 at 03:56):
Hi all,
I have this data type:
inductive Term
| Var : Nat → Term
deriving BEq, Repr
And I am trying to fill in the sorry
s here:
instance instLawfulBEq : LawfulBEq Term where
eq_of_beq := sorry
rfl := sorry
Eric Paul (Mar 22 2025 at 05:26):
Here's a related conversation you might find useful: #new members > Problem deriving LawfulBEq
It seemed to recommend deriving DecidableEq
instead.
Ben Selfridge (Mar 22 2025 at 05:45):
Thanks, very helpful -- however, now I am in a rabbit hole trying to define a DecidableEq
instance; I'm getting the "default handlers have not been implemented yet, class: 'DecidableEq' types: [Term]" error when I try to derive it.
Matt Diamond (Mar 22 2025 at 05:51):
I don't think a function from Nat
is going to have decidable equality unless the codomain is a subsingleton... we can't check all the inputs
Ben Selfridge (Mar 22 2025 at 05:59):
Let me explain better. I want to write code that evaluates (Var 3 == Var 3) for branching purposes, and I want to be able to reason about it. I'm having trouble doing that because I'm unable to convert between (Var 3 == Var 3) = true and (Var 3 = Var 3).
Vlad Tsyrklevich (Mar 22 2025 at 06:38):
can you provide an #mwe?
Chris Bailey (Mar 22 2025 at 07:00):
Unless you need to do it by defining BEq first, it's probably easier to do it the other way (derive DecidableEq, then define BEq in terms of that). The derived instances are usually behind auxiliary definitions and might have slightly artificial looking definitions, but Eq is just Eq.
inductive Term
| Var : Nat → Term
deriving DecidableEq, Repr
instance : BEq Term where
beq a b := a = b
instance instLawfulBEq : LawfulBEq Term where
eq_of_beq := by simp only [beq_iff_eq, imp_self, implies_true]
rfl := by simp only [beq_self_eq_true, implies_true]
open Term
example : ((Var 3 == Var 3) = true) = (Var 3 = Var 3) := by
simp only
Ben Selfridge (Mar 22 2025 at 07:01):
Here is a #mwe:
mutual
inductive Foo where
| Foo : Foo
| Bar : Bar → Foo
deriving DecidableEq
inductive Bar where
| Bar : Bar
deriving DecidableEq
inductive Baz where
| Bar : Bar → Baz
| Baz : Baz → Baz
structure Barf where
p : Option Baz
end
Ben Selfridge (Mar 22 2025 at 07:02):
Idk if it's minimal, but it's as minimal as i could make it.
Ben Selfridge (Mar 22 2025 at 07:03):
I'm unable to derive DecidableEq here. But if I comment out the Barf
declaration, it all works fine.
Ben Selfridge (Mar 22 2025 at 07:04):
Here it is, even more minimal:
mutual
inductive Foo where
| Foo : Foo
deriving DecidableEq
structure Barf where
p : Option Foo
deriving DecidableEq
end
Chris Bailey (Mar 22 2025 at 07:04):
Is your actual problem with Term
or with a mutual inductive?
Ben Selfridge (Mar 22 2025 at 07:05):
Looks like it's with a mutual inductive.
Chris Bailey (Mar 22 2025 at 07:06):
These are not mutual. Foo is not defined in terms of Barf.
Ben Selfridge (Mar 22 2025 at 07:07):
I know. But why does that matter? If I comment out the deriving
clauses, it works fine. Also note: I need the mutual
declaration in my actual code, even though it's not necessary in this MWE.
Ben Selfridge (Mar 22 2025 at 07:09):
Screenshot 2025-03-22 at 12.08.39 AM.png
Screenshot 2025-03-22 at 12.08.55 AM.png
Chris Bailey (Mar 22 2025 at 07:10):
Ben Selfridge said:
I know. But why does that matter? If I comment out the
deriving
clauses, it works fine. Also note: I need themutual
declaration in my actual code, even though it's not necessary in this MWE.
Then it's not really an MWE I'm afraid. It matters because not all deriving handlers work the same (or at all) for mutual inductives.
Ben Selfridge (Mar 22 2025 at 07:11):
Do you have any suggestions as to how I could define DecidableEq
inside that mutual inductive?
Ben Selfridge (Mar 22 2025 at 07:12):
Also, can you explain to me why I am getting the red squiggly line under DecidableEq
?
Ben Selfridge (Mar 22 2025 at 07:14):
I am so confused by your responses, I have to be honest with you. :(
Chris Bailey (Mar 22 2025 at 07:21):
You'll have to write it manually. The red squiggly is because the metaprogram for deriving DecidableEq
works for inductive types, but has not yet been extended to work for mutual or nested inductive types, hence needing to do it manually.
An example of doing it manually with an actual mutual would be like:
mutual
inductive A
| base : A
| mk : A -> B -> A
inductive B
| base : B
| mk : B -> A -> B
end
mutual
instance instDecidableEqA : DecidableEq A :=
fun
| .base, .base => isTrue rfl
| .base, .mk _ _ => isFalse (fun hf => by simp at hf)
| .mk _ _, .base => isFalse (fun hf => by simp at hf)
| .mk a₁ b₁, .mk a₂ b₂ =>
match instDecidableEqA a₁ a₂ with
| isTrue ht =>
match instDecidableEqB b₁ b₂ with
| isTrue ht' => isTrue <| (A.mk.injEq _ _ _ _).mpr ⟨ht, ht'⟩
| isFalse hf' => isFalse (fun hf => hf' ((A.mk.injEq _ _ _ _).mp hf).right)
| isFalse hf' => isFalse (fun hf => hf' ((A.mk.injEq _ _ _ _).mp hf).left)
instance instDecidableEqB : DecidableEq B :=
fun
| .base, .base => isTrue rfl
| .base, .mk _ _ => isFalse (fun hf => by simp at hf)
| .mk _ _, .base => isFalse (fun hf => by simp at hf)
| .mk b₁ a₁, .mk b₂ a₂ =>
match instDecidableEqA a₁ a₂ with
| isTrue ht =>
match instDecidableEqB b₁ b₂ with
| isTrue ht' => isTrue <| (B.mk.injEq _ _ _ _).mpr ⟨ht', ht⟩
| isFalse hf' => isFalse (fun hf => hf' ((B.mk.injEq _ _ _ _).mp hf).left)
| isFalse hf' => isFalse (fun hf => hf' ((B.mk.injEq _ _ _ _).mp hf).right)
end
Or this one (which is a nested inductive, but still):
Chris Bailey (Mar 22 2025 at 07:24):
Actually the A/B
one is sort of a loaded example, hold on.
Ben Selfridge (Mar 22 2025 at 07:27):
This is starting to look pretty spooky for something that seems so simple...
Chris Bailey (Mar 22 2025 at 07:40):
It's just case analysis. If you want everything to work out of the box and be simple, I would try to restate the problem without using a mutual inductive.
Chris Bailey (Mar 22 2025 at 07:42):
Or use BEq without worrying about the lawful part, in which case it literally is just case analysis as you would write in any other language that doesn't concern itself with proofs.
Ben Selfridge (Mar 22 2025 at 07:43):
I'll take a closer look at this tomorrow. Thank you very much for your responses
Ben Selfridge (Mar 22 2025 at 15:11):
Ok. Finally got all the DecidableEq instances written, thanks to your suggestions. It was incredibly tedious and I am not good enough with tactic combinators yet to know how to shorten it, but at least it's done. Thanks!
Last updated: May 02 2025 at 03:31 UTC