Imports
import Mathlib.Tactic

API for ExistsUnique

Here we review some of the API provided for ExistsUnique in Mathlib, and provide some additional tools. (Some of these might be suitable for upstreaming to Mathlib.)

existsUnique_of_exists_of_unique.{u_1} {α : Sort u_1} {p : α Prop} (hex : x, p x) (hunique : (y₁ y₂ : α), p y₁ p y₂ y₁ = y₂) : ∃! x, p x#check existsUnique_of_exists_of_unique
existsUnique_of_exists_of_unique.{u_1} {α : Sort u_1} {p : α  Prop} (hex :  x, p x)
  (hunique :  (y₁ y₂ : α), p y₁  p y₂  y₁ = y₂) : ∃! x, p x
ExistsUnique.exists.{u_1} {α : Sort u_1} {p : α Prop} : (∃! x, p x) x, p x#check ExistsUnique.exists
ExistsUnique.exists.{u_1} {α : Sort u_1} {p : α  Prop} : (∃! x, p x)   x, p x
ExistsUnique.unique.{u_1} {α : Sort u_1} {p : α Prop} (h : ∃! x, p x) {y₁ y₂ : α} (py₁ : p y₁) (py₂ : p y₂) : y₁ = y₂#check ExistsUnique.unique
ExistsUnique.unique.{u_1} {α : Sort u_1} {p : α  Prop} (h : ∃! x, p x) {y₁ y₂ : α} (py₁ : p y₁) (py₂ : p y₂) : y₁ = y₂
ExistsUnique.intro.{u_1} {α : Sort u_1} {p : α Prop} (w : α) (h₁ : p w) (h₂ : (y : α), p y y = w) : ∃! x, p x#check ExistsUnique.intro
ExistsUnique.intro.{u_1} {α : Sort u_1} {p : α  Prop} (w : α) (h₁ : p w) (h₂ :  (y : α), p y  y = w) : ∃! x, p x

This implements the axiom of unique choice.

noncomputable def ExistsUnique.choose {α: Sort*} {p: α Prop} (h : ∃! x, p x) : α := h.exists.choose
theorem ExistsUnique.choose_spec {α: Sort*} {p: α Prop} (h : ∃! x, p x) : p h.choose := h.exists.choose_spectheorem ExistsUnique.choose_eq {α: Sort*} {p: α Prop} (h : ∃! x, p x) {x : α} (hx : p x) : h.choose = x := h.unique h.choose_spec hxtheorem ExistsUnique.choose_iff {α: Sort*} {p: α Prop} (h : ∃! x, p x) (x : α): p x x = h.choose := α:Sort u_1p:α Proph:∃! x, p xx:αp x x = h.choose α:Sort u_1p:α Proph:∃! x, p xx:αhx:p xx = h.choose; All goals completed! 🐙, α:Sort u_1p:α Proph:∃! x, p xx:αx = h.choose p x α:Sort u_1p:α Proph:∃! x, p xp h.choose; All goals completed! 🐙 theorem ExistsUnique.choose_eq_choose {α: Sort*} {p: α Prop} (h : ∃! x, p x) : Exists.choose h = h.choose := α:Sort u_1p:α Proph:∃! x, p xExists.choose h = h.choose α:Sort u_1p:α Proph:∃! x, p xp (Exists.choose h); All goals completed! 🐙

An alternate form of the axiom of unique choice.

noncomputable def Subsingleton.choose {α: Sort*} [Subsingleton α] [hn: Nonempty α] : α := hn.some
theorem Subsingleton.choose_spec {α: Sort*} [hs: Subsingleton α] [Nonempty α] (x:α) : x = hs.choose := Subsingleton.elim _ _

The equivalence between ExistsUnique and Subsingleton/Nonempty does not require choice.

theorem ExistsUnique.iff_subsingleton_nonempty {α: Sort*} {p: α Prop} : (∃! x, p x) (Subsingleton {x // p x} Nonempty {x // p x}) := α:Sort u_1p:α Prop(∃! x, p x) Subsingleton { x // p x } Nonempty { x // p x } α:Sort u_1p:α Prop(∃! x, p x) Subsingleton { x // p x } Nonempty { x // p x }α:Sort u_1p:α PropSubsingleton { x // p x } Nonempty { x // p x } ∃! x, p x α:Sort u_1p:α Prop(∃! x, p x) Subsingleton { x // p x } Nonempty { x // p x } α:Sort u_1p:α Proph:∃! x, p xSubsingleton { x // p x } Nonempty { x // p x }; α:Sort u_1p:α Proph:∃! x, p xx₀:αhx₀:p x₀Subsingleton { x // p x } Nonempty { x // p x } α:Sort u_1p:α Proph:∃! x, p xx₀:αhx₀:p x₀ (a b : { x // p x }), a = b intro x, hx α:Sort u_1p:α Proph:∃! x, p xx₀:αhx₀:p x₀x:αhx:p xy:αhy:p yx, hx = y, hy All goals completed! 🐙 α:Sort u_1p:α Prophsing:Subsingleton { x // p x }x₀:αhx₀:p x₀∃! x, p x α:Sort u_1p:α Prophsing:Subsingleton { x // p x }x₀:αhx₀:p x₀ (y : α), p y y = x₀; intro y α:Sort u_1p:α Prophsing:Subsingleton { x // p x }x₀:αhx₀:p x₀y:αhy:p yy = x₀ All goals completed! 🐙
'ExistsUnique.iff_subsingleton_nonempty' depends on axioms: [propext]#print axioms ExistsUnique.iff_subsingleton_nonempty
'ExistsUnique.iff_subsingleton_nonempty' depends on axioms: [propext]