Zulip Chat Archive

Stream: mathlib4

Topic: EReal


Michael Stoll (Jan 02 2024 at 11:50):

Context: The abscissa of (absolute) convergence of an L-series is naturally an EReal (i.e., between -∞ and ∞ inclusive). So I need to work with EReals in this context. See also here.

My most fundamental question in this regard is: can we hide the ugly implementation-detail asymmetry of the definition and have cases x (with x : EReal) accept three match arms of the form ⊥ => ..., ⊤ => ... and (Real.toEReal y) => ...? I can use match x with, but then I have to write some (some y) in the last alternative and in many cases change that to ↑y manually to be able to work with it.

One attempt:

import Mathlib.Data.Real.EReal

lemma EReal.elim {α : EReal  Sort*} (motive : EReal) (hb : α ) (ht : α ) (hr :  y : , α y) :
    α motive :=
  match motive with
  |  => hb
  |  => ht
  | (some (some y)) => hr y

syntax (name := casesEReal) "casesEReal" term "with" term : tactic

macro_rules | `(tactic| casesEReal $x:term with $y:term) => `(tactic|
  refine EReal.elim $x ?_ ?_ (fun $y  ?_))

variable (P : EReal  Prop)

example (x : EReal) : P x := by
  casesEReal x with y
  -- 3 goals: ⊢ P ⊥, ⊢ P ⊤, y: ℝ ⊢ P ↑y
  all_goals sorry

But it would be nice to teach the existing cases, rcasesetc. to use EReal.elim. Is this at all possible?

Antoine Chambert-Loir (Jan 02 2024 at 12:11):

Isn't it docs#EReal.rec (up to the order of parameters)?

Michael Stoll (Jan 02 2024 at 12:13):

I missed that somehow.
Still, induction x using EReal.rec feels a bit unnatural as there is no induction hypothesis.

Yaël Dillies (Jan 02 2024 at 12:15):

Sadly, custom default recursors are not there yet. We've been wanting them for a while.

Michael Stoll (Jan 02 2024 at 12:16):

... and induction x using EReal.rec with y apparently does not work to name the real number in the main case...

Michael Stoll (Jan 02 2024 at 12:17):

...using case labels is also ugly:

lemma exists_between_ofReal_left {x : EReal} {z : } (h : x < z) :  y : , x < y  y < z := by
  obtain a, ha₁, ha₂ := exists_between h
  induction a using EReal.rec
  case intro.intro.h_bot => simp only [not_lt_bot] at ha₁
  case intro.intro.h_top => simp only [not_top_lt] at ha₂
  case intro.intro.h_real a₀ => exact a₀, by exact_mod_cast ha₁, by exact_mod_cast ha₂

Yaël Dillies (Jan 02 2024 at 12:17):

Michael Stoll said:

... and induction x using EReal.rec with y apparently does not work to name the real number in the main case...

Have you tried induction' x using EReal.rec with y?

Michael Stoll (Jan 02 2024 at 12:17):

Can that be improved so that the case have names like bot, top and ofReal?

Yaël Dillies (Jan 02 2024 at 12:18):

Once again, this is a missing Lean feature that we've been petitioning for

Michael Stoll (Jan 02 2024 at 12:19):

induction' allows to name the variable, but I got the impression that induction' is a crutch used for the port of mathlib.

Yaël Dillies (Jan 02 2024 at 12:19):

It was originally presented that way, but the new induction syntax is so unergonomic that I really doubt we'll actually switch from induction' to induction everywhere.

Michael Stoll (Jan 02 2024 at 12:19):

I assume using the case names is preferred as that does not rely implicitly on the order of arguments of EReal.rec. So it would be nice to have nicer names.

Yaël Dillies (Jan 02 2024 at 12:20):

That too is really up for debate.

Eric Rodriguez (Jan 02 2024 at 12:20):

Yaël Dillies said:

It was originally presented that way, but the new induction syntax is so unergonomic that I really doubt we'll actually switch from induction' to induction everywhere.

I think this is the long-term idea, although I'm not a tremendous fan either, to be honest.

Alex J. Best (Jan 02 2024 at 14:23):

You can tag your lemma with @[eliminator] seems to work fine to me

import Mathlib.Data.Real.EReal
@[eliminator]
lemma EReal.elim {α : EReal  Sort*} (motive : EReal) (hb : α ) (ht : α ) (hr :  y : , α y) :
    α motive :=
  match motive with
  |  => hb
  |  => ht
  | (some (some y)) => hr y

syntax (name := casesEReal) "casesEReal" term "with" term : tactic

macro_rules | `(tactic| casesEReal $x:term with $y:term) => `(tactic|
  refine EReal.elim $x ?_ ?_ (fun $y  ?_))

variable (P : EReal  Prop)

example (x : EReal) : P x := by
  casesEReal x with y
  -- 3 goals: ⊢ P ⊥, ⊢ P ⊤, y: ℝ ⊢ P ↑y
  all_goals sorry

example (x : EReal) : P x := by
  cases x
  -- 3 goals: ⊢ P ⊥, ⊢ P ⊤, y: ℝ ⊢ P ↑y
  all_goals sorry

Michael Stoll (Jan 02 2024 at 14:26):

Then also cases' x with y works.
However, the yellow lightbulb appearing on cases still generates cases none and some val...

Michael Stoll (Jan 02 2024 at 14:27):

Would it be reasonable to add this to Mathlib as well?

Alex J. Best (Jan 02 2024 at 14:28):

I think so yes, I think we are missing out by not using this feature more.
And the light bulb thing sounds like a bug indeed!

Mario Carneiro (Jan 02 2024 at 14:28):

I don't think the code action supports cases using

Michael Stoll (Jan 02 2024 at 14:29):

But cases works without using?

Mario Carneiro (Jan 02 2024 at 14:30):

yes?

Mario Carneiro (Jan 02 2024 at 14:30):

sorry I'm not sure what the bug report is here

Michael Stoll (Jan 02 2024 at 14:30):

import Mathlib.Data.Real.EReal

@[eliminator]
lemma EReal.elim {α : EReal  Sort*} (motive : EReal)
    (bot : α ) (top : α ) (ofReal :  y : , α y) :
    α motive :=
  match motive with
  |  => bot
  |  => top
  | (some (some y)) => ofReal y

variable (P : EReal  Prop)

example (x : EReal) : P x := by
  cases x with
  | bot => sorry
  | top => sorry
  | ofReal y => sorry

Mario Carneiro (Jan 02 2024 at 14:30):

oh, you are using @[eliminator] as an auto-using

Mario Carneiro (Jan 02 2024 at 14:30):

yeah that's not supported either

Michael Stoll (Jan 02 2024 at 14:30):

Which eliminator is picked by cases and which by the lightbulb?

Mario Carneiro (Jan 02 2024 at 14:31):

in fact it will probably cause things to be really weird since it will generate case names that don't match what cases thinks

Mario Carneiro (Jan 02 2024 at 14:31):

the code action only ever looks at the inductive type

Mario Carneiro (Jan 02 2024 at 14:31):

i.e. as if you didn't use using or @[eliminator]

Alex J. Best (Jan 02 2024 at 14:31):

I guess https://github.com/leanprover/std4/blob/03a0f24da542fcf3fd60d9a9de9db6c5af0391f7/Std/CodeAction/Misc.lean#L283 is the relevant code, the code action just uses typename.casesOn

Michael Stoll (Jan 02 2024 at 14:32):

So we should redefine EReal.casesOn? (If that's possible...)

Mario Carneiro (Jan 02 2024 at 14:33):

what's the goal?

Michael Stoll (Jan 02 2024 at 14:33):

To have cases x give the natural trichotomy on x : EReal (and the lightbulb to do the same).

Mario Carneiro (Jan 02 2024 at 14:33):

the lightbulb thing is a bug, it doesn't reflect what cases actually does and gives wrong hints as a result. Assuming that issue is fixed, are there any other bugs?

Alex J. Best (Jan 02 2024 at 14:33):

The goal is that in the presence of @[eliminator] the light bulb produces working code

Alex J. Best (Jan 02 2024 at 14:34):

No I think thats it!


Last updated: May 02 2025 at 03:31 UTC