Zulip Chat Archive

Stream: general

Topic: Nat term is equal to 0 or _ + 1


Peter Nelson (Apr 22 2024 at 13:42):

As part of teaching, I'm thinking about the following issue. In the middle of a proof, I have (something complicated) : Nat, and want to divide into cases where the complicated expression is 0 or equal to _ + 1, with minimal fuss. Something like the below is more fuss than I'd like, since it requires typing out the statement that I need fully, as well as a proof, and it includes the word 'induction', which is likely confusing to a mathematically literate novice.

import Mathlib.Tactic

example (f : α  ) (a : α) : False := by
  obtain (h0 | k,hak : f a = 0   k, f a = k + 1) := by induction f a <;> simp
  · -- solve the case `f a = 0`
    sorry
  -- solve the case `f a = k + 1`
  sorry

So my real question is why the following isn't in mathlib. Is there an approach to the above that I'm missing?

theorem Nat.exists_eq_zero_or_add_one (n : ) : (n = 0)   m, n = m + 1 := by
  induction n <;> simp

I'm also having an analogous issue splitting an ENat into the infinite and finite cases, where the relevant short proof is a bit longer and more annoying.

Ruben Van de Velde (Apr 22 2024 at 13:43):

Well, induction n or cases n is exactly this

Peter Nelson (Apr 22 2024 at 13:43):

So what would that look like applied in the first example?

Ruben Van de Velde (Apr 22 2024 at 13:45):

import Mathlib.Tactic

example (f : α  ) (a : α) : False := by
  cases h : f a with
  | zero =>
    -- solve the case `f a = 0`
    sorry
  | succ n =>
    -- solve the case `f a = k + 1`
    sorry

Peter Nelson (Apr 22 2024 at 13:46):

That gives me zero and succ instead of 0 and +1. Can we not do better for the purposes of teaching?

Peter Nelson (Apr 22 2024 at 13:47):

The approach also does annoying things that need rewriting in the ENat case.

Ruben Van de Velde (Apr 22 2024 at 13:51):

I think this may be fixed in an upcoming version of lean for Nat. For ENat you can use

import Mathlib

example (a : ENat) (P : ENat  Prop) : P a := by
  cases a using ENat.recTopCoe with
  | top => sorry
  | coe n => sorry

Peter Nelson (Apr 22 2024 at 13:58):

How would I do this?

example (a : α) (f : α  ) (P :   Prop) (htop : P )
    (h_coe :  (a : α) (n : ), f a = n  P (f a)) : P (f a) := by
  cases f a using ENat.recTopCoe with
  | top =>
    exact htop
  | coe n =>
    -- Nothing like `f a = ↑n` is in the context here.
    sorry

Ruben Van de Velde (Apr 22 2024 at 14:02):

cases h : f a using ENat.recTopCoe with

Peter Nelson (Apr 22 2024 at 14:03):

Right - it's the annotation h : _ in cases that I've been missing. That answers my question - thanks!

Kyle Miller (Apr 22 2024 at 14:20):

Peter Nelson said:

That gives me zero and succ instead of 0 and +1. Can we not do better for the purposes of teaching?

Just to confirm, we do have this improvement in the next release of Lean. You'll see this for induction/cases/rcases/obtain/rintro

Mark Fischer (Apr 22 2024 at 16:30):

Would it make sense to let Cases act more like Match when the arms (| _ => ,,,) are present? (Ie, give them full pattern matching and exhaustiveness checking)

Eric Wieser (Apr 22 2024 at 20:37):

Why not just use match in that case?

Mark Fischer (Apr 23 2024 at 02:41):

Eric Wieser said:

Why not just use match in that case?

Yeah, that's fair enough. I suppose it avoids switching from tactics to terms? Lessons some cognitive load, but it just pushes it down the line to tactics like inductive.

Probably not a good enough reason though.

Kim Morrison (Apr 23 2024 at 03:08):

I'd suggest not thinking of match as "switching to terms". Note that when you use match in tactic mode, you are still in tactic mode after the =>.


Last updated: May 02 2025 at 03:31 UTC