expand_exists
#
expand_exists
is an attribute which takes a proof that something exists with some property, and
outputs a value using classical.some
, and a proof that it has that property using
classical.some_spec
. For example:
@[expand_exists it it_spec]
lemma it_exists (n : ℕ) : ∃ m : ℕ, n < m := sorry
produces
def it (n : ℕ) : ℕ := classical.some (it_exists n)
lemma it_spec (n : ℕ) : n < it n := classical.some_spec (it_exists n)
```
From a proof that (a) value(s) exist(s) with certain properties, constructs (an) instance(s) satisfying those properties. For instance:
@[expand_exists nat_greater nat_greater_spec]
lemma nat_greater_exists (n : ℕ) : ∃ m : ℕ, n < m := ...
#check nat_greater -- nat_greater : ℕ → ℕ
#check nat_greater_spec -- nat_greater_spec : ∀ (n : ℕ), n < nat_greater n
It supports multiple witnesses:
@[expand_exists nat_greater_m nat_greater_l nat_greater_spec]
lemma nat_greater_exists (n : ℕ) : ∃ (m l : ℕ), n < m ∧ m < l := ...
#check nat_greater_m -- nat_greater : ℕ → ℕ
#check nat_greater_l -- nat_greater : ℕ → ℕ
#check nat_greater_spec-- nat_greater_spec : ∀ (n : ℕ),
n < nat_greater_m n ∧ nat_greater_m n < nat_greater_l n
It also supports logical conjunctions:
@[expand_exists nat_greater nat_greater_lt nat_greater_nonzero]
lemma nat_greater_exists (n : ℕ) : ∃ m : ℕ, n < m ∧ m ≠ 0 := ...
#check nat_greater -- nat_greater : ℕ → ℕ
#check nat_greater_lt -- nat_greater_lt : ∀ (n : ℕ), n < nat_greater n
#check nat_greater_nonzero -- nat_greater_nonzero : ∀ (n : ℕ), nat_greater n ≠ 0
Note that without the last argument nat_greater_nonzero
, nat_greater_lt
would be:
#check nat_greater_lt -- nat_greater_lt : ∀ (n : ℕ), n < nat_greater n ∧ nat_greater n ≠ 0
```