Zulip Chat Archive
Stream: lean4
Topic: getting `aesop` to use cases with custom cases eliminators
Robin Carlier (Mar 25 2025 at 07:29):
Consider this #mwe (which is probably not as minimal as it could be)
import Mathlib.Logic.Unique
import Aesop
inductive CustomType
| left
| right
attribute [local aesop safe cases] CustomType -- works
def CustomHom : CustomType → CustomType → Type
| .left, .left => PUnit
| .right, .left => PEmpty
| .left, .right => PUnit
| .right, .right => PUnit
instance : Unique (CustomHom .left .left) := inferInstanceAs (Unique PUnit)
instance : Unique (CustomHom .left .right) := inferInstanceAs (Unique PUnit)
instance : Unique (CustomHom .right .right) := inferInstanceAs (Unique PUnit)
@[elab_as_elim, cases_eliminator, induction_eliminator]
def customHomInduction
{P : {x y : CustomType} → (CustomHom x y) → Sort*}
(left : P (default : CustomHom .left .left))
(right : P (default : CustomHom .right .right))
(left_right : P (default : CustomHom .left .right))
{x y : CustomType} (f : CustomHom x y) : P f :=
match x, y, f with
| .left, .left, _ => left
| .right, .right, _ => right
| .left, .right, _ => left_right
attribute [local aesop safe cases] CustomHom -- fails
Are there some aesop magic words to get aesop
to call cases
on hypotheses of the form f : CustomHom x y
?
Jannis Limperg (Mar 26 2025 at 15:48):
This works:
import Mathlib.Logic.Unique
import Aesop
inductive CustomType
| left
| right
attribute [local aesop safe cases] CustomType -- works
def CustomHom : CustomType → CustomType → Type
| .left, .left => PUnit
| .right, .left => PEmpty
| .left, .right => PUnit
| .right, .right => PUnit
instance : Unique (CustomHom .left .left) := inferInstanceAs (Unique PUnit)
instance : Unique (CustomHom .left .right) := inferInstanceAs (Unique PUnit)
instance : Unique (CustomHom .right .right) := inferInstanceAs (Unique PUnit)
@[elab_as_elim, cases_eliminator, induction_eliminator]
def customHomInduction
{P : {x y : CustomType} → (CustomHom x y) → Sort*}
(left : P (default : CustomHom .left .left))
(right : P (default : CustomHom .right .right))
(left_right : P (default : CustomHom .left .right))
{x y : CustomType} (f : CustomHom x y) : P f := by
aesop (add norm unfold CustomHom)
The issue is that Aesop needs to be told to reduce CustomHom .right .left
to PEmpty
; after that it does cases
on PEmpty
via a built-in rule.
Jannis Limperg (Mar 26 2025 at 15:50):
Another way:
import Mathlib.Logic.Unique
import Aesop
inductive CustomType
| left
| right
attribute [local aesop safe cases] CustomType -- works
def CustomHom : CustomType → CustomType → Type
| .left, .left => PUnit
| .right, .left => PEmpty
| .left, .right => PUnit
| .right, .right => PUnit
instance : Unique (CustomHom .left .left) := inferInstanceAs (Unique PUnit)
instance : Unique (CustomHom .left .right) := inferInstanceAs (Unique PUnit)
instance : Unique (CustomHom .right .right) := inferInstanceAs (Unique PUnit)
@[aesop norm forward]
theorem customHom_right_left_false : CustomHom .right .left → False := nofun
@[elab_as_elim, cases_eliminator, induction_eliminator]
def customHomInduction
{P : {x y : CustomType} → (CustomHom x y) → Sort*}
(left : P (default : CustomHom .left .left))
(right : P (default : CustomHom .right .right))
(left_right : P (default : CustomHom .left .right))
{x y : CustomType} (f : CustomHom x y) : P f := by
aesop
Robin Carlier (Mar 26 2025 at 16:19):
I am a bit confused, I was not asking how I could get aesop
to prove customHomInduction
, but rather how to tell aesop to use customCaseInduction
as a cases rule in other goals for other lemmas once it’s proven. Are you telling me that this is in fact what aesop norm forward
or aesop norm unfold
achieves?
Jannis Limperg (Mar 26 2025 at 16:25):
Ah, I see. Registering custom eliminators as cases
rules is currently not supported (unfortunately). But if you use the proposed Aesop rules, they should be equivalent to registering customHomInduction
: for any hypothesis f : CustomHom x y
, the rules will perform cases
on x
and y
, then close the resulting subgoal for x = right
and y = left
, leaving you with the three cases that would have been generated by customHomInduction
.
The only downside of this approach is that cases
will also be run on any hypotheses x : CustomType
that don't appear in a CustomHom
hyp.
Robin Carlier (Mar 26 2025 at 16:28):
Given that I am fine with attribute [local aesop safe cases] CustomType
, I’m okay with aesop callin cases on every x : CustomType
in context, thanks!
Last updated: May 02 2025 at 03:31 UTC