Zulip Chat Archive

Stream: new members

Topic: How can I say "there exist unique a, b such that..."?


Adam Dingle (Feb 10 2024 at 12:25):

I'd like to translate this statement into Lean: "There is a unique pair of natural numbers (a, b) such that a * b = 1."

I can write

  example: ∃! (p : Nat × Nat), p.1 * p.2 = 1 := ...

But p.1 and p.2 are a bit ugly. Really I'd like to write

  example: ∃! ((a, b) : Nat × Nat), a * b = 1 := ...

but Lean won't accept this syntax. Is there any way to write this nicely?

Ruben Van de Velde (Feb 10 2024 at 12:41):

This could work: example: ∃! (a : Nat) (b : Nat), a * b = 1 := ...

Adam Dingle (Feb 10 2024 at 12:45):

I believe that Lean interprets that as meaning ∃! (a : Nat), ∃! (b : Nat), a * b = 1, which is not semantically the same.

Josha Dekker (Feb 10 2024 at 12:46):

So perhaps take (a, b) to be an element of Nat x Nat?

Adam Dingle (Feb 10 2024 at 12:47):

I realized that this works:

example: ∃!(p : Nat × Nat), let (x, y) := p;
  x * y = 1 := ...

This isn't too bad. I'd still be happy to know about a nicer syntax if it exists.

Adam Dingle (Feb 10 2024 at 12:48):

Josha: I don't understand your comment. Are you suggesting a particular syntax that will work?

Ruben Van de Velde (Feb 10 2024 at 12:57):

They are provably the same though, no?

Josha Dekker (Feb 10 2024 at 13:02):

Adam Dingle said:

I realized that this works:

example: ∃!(p : Nat × Nat), let (x, y) := p;
  x * y = 1 := ...

This isn't too bad. I'd still be happy to know about a nicer syntax if it exists.

This is basically what I was suggesting indeed: you want to say that there is a unique pair of integers, so you consider the set of all pairs of integers, i.e. Nat x Nat

Josha Dekker (Feb 10 2024 at 13:03):

I think there’s a way of doing the ‘let’ part immediately, but I’m not sure about that.

Edward van de Meent (Feb 10 2024 at 13:04):

i believe you can do ((x,y): Nat \x Nat)

Adam Dingle (Feb 10 2024 at 13:07):

Lean won't accept that syntax. If I write

example: ∃! ((x, y) : Nat × Nat), x * y = 1 := sorry

Lean reports

unexpected token '('; expected '_' or identifier

at the left parenthesis in (x, y).

Edward van de Meent (Feb 10 2024 at 13:08):

oh...

Edward van de Meent (Feb 10 2024 at 13:08):

in that case, maybe just \exists! (x y : Nat),...?

Johan Commelin (Feb 10 2024 at 13:16):

Note that \exists! x, \exists! y, foo(x, y) does not mean the same thing as \exists! (x, y), foo(x, y).

Edward van de Meent (Feb 10 2024 at 13:18):

ah right... and i'm guessing that what i suggested expands to the first?

Eric Wieser (Feb 10 2024 at 13:19):

example : ExistsUnique fun (a, b) => a * b = 1 := _ works, but not with notation

Dan Velleman (Feb 10 2024 at 22:06):

You could also say: ∃ (a b : Nat), a * b = 1 ∧ ∀ (a' b' : Nat), a' * b' = 1 → a' = a ∧ b' = b.

Kevin Buzzard (Feb 10 2024 at 22:11):

They are provably the same though, no?

@Adam Dingle @Ruben Van de Velde they are provably different! This is a fabulous gotcha. Saying "there's a unique a such that there's a unique b which works" allows the possibility that there's an a for which only one b works, but for all the other a's, more than one b works (as opposed to no b working)

import Mathlib.Tactic

example :  (P :     Prop),
    ¬ ((∃! (a : ) (b : ), P a b)  (∃! ab :  × , P ab.1 ab.2)) := by
  use fun a b => (a = 0)  (b = 0)
  rintro h1, - -- left->right is the problem
  specialize h1 0, 0, id, by aesop⟩, fun c d, hd1, hd2 => ?_
  · specialize hd2 (d+1)
    aesop
  · rcases h1 with ⟨⟨a, b⟩, -, hab
    specialize hab (a+1, b+1)
    aesop

Kyle Miller (Feb 11 2024 at 00:50):

Here are some concrete examples:

example : ∃! (y x : Int), y = x^2 := by
  use 0
  constructor
  · use 0
    simp
    intro _ h
    exact pow_eq_zero h.symm
  · simp
    rintro y x, h
    simp at h
    cases h.1
    simp at h
    specialize h (-x)
    simpa using h

example : ¬ ∃! (x y : Int), y = x^2 := by
  rintro x, h
  simp at h
  specialize h (x + 1)
  simp at h

example : ¬ ∃! p : Int × Int, p.1 = p.2^2 := by
  rintro ⟨⟨y, x⟩, h
  simp at h
  cases h.1
  simp at h
  specialize h ((x+1)^2) (x+1)
  simp at h

Junyan Xu (Feb 11 2024 at 01:31):

cross link

Ruben Van de Velde (Feb 11 2024 at 07:58):

Thanks for the explanation, Kevin! Now I understand why I didn't manage to prove the equivalence :)

Eric Wieser (Apr 17 2024 at 16:02):

In lean 3 we were stuck with this behavior because notation was inflexible; can we just make ∃! (x y : Int), an error now?

Kyle Miller (Apr 17 2024 at 16:27):

@Eric Wieser mathlib4#12218

Kyle Miller (Apr 17 2024 at 17:29):

If anyone wants to help with the errors, all you need to do is turn expressions like ∃! (b : _) (_ : b ∈ c), a ∈ b into ∃! b, ∃! _ : b ∈ c, a ∈ b. Notice the lack of parentheses, the ability to drop : _, and, furthermore, the fact that this isn't being re-stated more reasonably. (It would be more simple as ∃! b, b ∈ c ∧ a ∈ b.)

I figure a follow-up PR could review all uses of ∃! and clean them up.

Eric Wieser (Apr 17 2024 at 18:39):

I guess ExistsUnique could allow chained prop binders?

Kyle Miller (Apr 17 2024 at 20:10):

I think rather it would be good to have extended binder syntax so that ∃! b ∈ c, a ∈ b is ∃! b, b ∈ c ∧ a ∈ b, just like for Exists. That could be in that follow-up PR.

Mark Fischer (Apr 17 2024 at 21:18):

Is there a technical reason Lean doesn't allow destructuring in the parameter position?
Does it get weird with dependent types?

Kyle Miller (Apr 17 2024 at 21:19):

Lean allows it in fun, but there's some inconsistency between various notations that accept binders. The main issue is that if you allow destructuring, you get a match expression in the body of your quantifier.

Kyle Miller (Apr 17 2024 at 21:39):

Is docs#NumberField.Units.exist_unique_eq_mul_prod (the Dirichlet unit theorem) stated correctly?

Kevin Buzzard (Apr 17 2024 at 22:24):

My guess is no, and that the assertion is too weak

Kyle Miller (Apr 18 2024 at 09:27):

@Eric Wieser #12237

Kyle Miller (Apr 18 2024 at 09:49):

@Kevin Buzzard Thanks — here's a fix #12240


Last updated: May 02 2025 at 03:31 UTC