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