Zulip Chat Archive
Stream: general
Topic: How to propagate `@[simp, reducible]` through instances?
Andrej Bauer (Apr 09 2023 at 11:09):
Why does Lean 4 ignore @[simp, reducible]
in this case?
inductive Cow (α : Type) : Type
| tail : Cow α
| horn : α → Cow α
@[simp, reducible]
def Cow.le {α : Type} [LE α]: Cow α → Cow α → Prop :=
fun x y =>
match x with
| .tail => true
| .horn a =>
match y with
| .tail => false
| .horn b => a ≤ b
instance CowLT (α : Type) [LE α] : LE (Cow α) where
le := Cow.le
lemma Cow.moo (α : Type) [LE α] (x y : α) :
horn x ≤ horn y → x ≤ y := by simp -- this does not work
If I replace horn x ≤ horn y
in the lemma with Cow.le
then by simp
works.
Eric Wieser (Apr 09 2023 at 12:05):
You presumably need to mark CowLT [sic] reducible too
Andrej Bauer (Apr 09 2023 at 14:23):
Ah yes, that works. But what if the instance had many fields, can I annotate only some of them?
Eric Wieser (Apr 09 2023 at 14:42):
What's the motivation for making it reducible?
Andrej Bauer (Apr 09 2023 at 14:43):
I suspect I don't understand when reducible
should be used.
Eric Wieser (Apr 09 2023 at 14:44):
I'm not sure many people do; it's use pretty sparingly and somewhat arbitrarily in mathlib
Eric Wieser (Apr 09 2023 at 14:44):
Most of the time it's only used to alias a function or type with another name
Eric Wieser (Apr 09 2023 at 14:45):
I don't know if there are any places where it is used on instances.
Eric Wieser (Apr 09 2023 at 14:46):
Incidentally, your Cow
looks like docs4#WithBot
Andrej Bauer (Apr 09 2023 at 18:04):
Yes, I know, I wanted a self-contained example. It's more polite that way.
Eric Wieser (Apr 09 2023 at 18:09):
Andrej Bauer said:
Ah yes, that works. But what if the instance had many fields, can I annotate only some of them?
You can mark the instance as reducible and make all but some of the fields defined in terms of a not-reducible
implementation
Kyle Miller (Apr 09 2023 at 20:25):
One thing you can do is put @[simp]
on the instance (no need for reducible
anywhere), though it's not clear to me whether this is the correct design.
import Std.Logic
inductive Cow (α : Type) : Type
| tail : Cow α
| horn : α → Cow α
@[simp]
def Cow.le {α : Type} [LE α]: Cow α → Cow α → Prop :=
fun x y =>
match x with
| .tail => true
| .horn a =>
match y with
| .tail => false
| .horn b => a ≤ b
@[simp]
instance CowLT (α : Type) [LE α] : LE (Cow α) where
le := Cow.le
theorem Cow.moo (α : Type) [LE α] (x y : α) :
horn x ≤ horn y → x ≤ y := by simp
Kyle Miller (Apr 09 2023 at 20:28):
A problem with this is that simp
will always turn LE
for Cow
into Cow.le
, which isn't great. Another solution, which isn't great but at least limits the scope, is to not use @[simp]
and instead give simp
the definitions manually.
theorem Cow.moo (α : Type) [LE α] (x y : α) :
horn x ≤ horn y → x ≤ y := by simp [LE.le, Cow.le]
Last updated: Dec 20 2023 at 11:08 UTC