# Zulip Chat Archive

## Stream: new members

### Topic: How do I introduce a Forall in tactic mode

#### Lars Ericson (Nov 27 2020 at 01:04):

In this proof:

```
example : (∃ x, p x → r) ↔ (∀ x, p x) → r :=
begin
split,
{
intro h1,
intro h2,
cases h1 with x pxr,
have h2x := h2 x,
exact pxr h2x,
},
{
intro h,
constructor,
intro hp,
sorry
},
end
```

at the `sorry`

, my goal state is

```
2 goals
α : Type u_1,
p : α → Prop,
r : Prop,
h : (∀ (x : α), p x) → r,
hp : p ?m_1
⊢ r
α : Type u_1,
p : α → Prop,
r : Prop,
h : (∀ (x : α), p x) → r
⊢ α
```

In the first goal, I would like to generalize `hp : p ?m_1`

to be ` (∀ (x : α), p x) `

. What is the tactic-mode syntax to introduce the `∀`

?

#### Kevin Buzzard (Nov 27 2020 at 01:09):

I'm not sure this makes any sense. `hp`

says "p of some explicit element of alpha is true". I'm not sure what you mean by "generalize" but neither `hp`

nor what you want to "generalize" it to imply the other.

#### Kevin Buzzard (Nov 27 2020 at 01:11):

PS I'm not sure running `constructor`

on an exists goal is buying you much. You still have the same problem (constructing an element of alpha and proving it satisfies p) but you now have two goals, one of which is not a prop and the other of which has a metavariable in.

#### Donald Sebastian Leung (Nov 27 2020 at 01:55):

Is this even true though? For the reverse implication, if the type of `x`

is empty then no witness can be produced for proving the exists statement.

#### Lars Ericson (Nov 27 2020 at 04:09):

@Donald Sebastian Leung , it's an exercise in section 4.4. I just assumed it was true.

@Kevin Buzzard, I have been able to use `constructor`

for other exercises in this set, as a way of eliminating the quantifier in existential goals. For example

```
example : (∃ x, p x ∧ r) ↔ (∃ x, p x) ∧ r :=
begin
split,
{
intro h,
split,
{
cases h with x pxr,
have px := pxr.left,
constructor,
exact px,
},
{
cases h with x pxr,
exact pxr.right,
}
},
{
intro h,
cases h with h1 h2,
cases h1 with x px,
have hpxr := and.intro px h2,
constructor,
exact hpxr,
},
end
```

and

```
example : (∃ x, p x ∨ q x) ↔ (∃ x, p x) ∨ (∃ x, q x) :=
begin
split,
{
intro h,
cases h with x pxqx,
cases pxqx with px qx,
{
left,
constructor,
exact px,
},
{
right,
constructor,
exact qx,
},
},
{
intro h,
cases h with px qx,
{
cases px with x px,
have pxqx := or.intro_left (q x) px,
constructor,
exact pxqx,
},
{
cases qx with x qx,
have pxqx := or.intro_right (p x) qx,
constructor,
exact pxqx,
},
},
end
```

#### Bryan Gin-ge Chen (Nov 27 2020 at 04:10):

I think you have to use `variable a : α`

as in your earlier question today.

#### Lars Ericson (Nov 27 2020 at 04:12):

Of the exercises in Chapter 4 that deal with quantifiers, I am down to a number of them where I have subgoals of form `p ?m_1`

and `α`

. These involve less successful uses of `constructor`

than the above examples. The failure points are where you see `sorry`

:

```
open classical
open data.nat.basic
variables (α : Type*) (p q : α → Prop)
variable r : Prop
example : (∃ x, p x) ↔ ¬ (∀ x, ¬ p x) :=
begin
split,
{
intro h,
cases h with x px,
intro h,
have npx := h x,
exact npx px,
},
{
intro h,
constructor,
sorry,
sorry,
},
end
example : (¬ ∀ x, p x) ↔ (∃ x, ¬ p x) :=
begin
split,
{
intro h,
constructor,
intro h1,
sorry,
sorry,
},
{
intro h,
intro fx,
cases h with x npx,
have px := fx x,
exact npx px,
},
end
example : (∃ x, p x → r) ↔ (∀ x, p x) → r :=
begin
split,
{
intro h1,
intro h2,
cases h1 with x pxr,
have h2x := h2 x,
exact pxr h2x,
},
{
intro h,
constructor,
intro hp,
apply h,
intro,
sorry,
sorry,
},
end
example : (∃ x, r → p x) ↔ (r → ∃ x, p x) :=
begin
split,
{
intro h1,
intro h2,
constructor,
{
cases h1 with x rpx,
have px := rpx h2,
sorry
},
sorry,
},
{
intro h,
constructor,
{
intro h1,
have h2 := h h1,
cases h2 with x px,
sorry,
},
sorry,
},
end
```

#### Lars Ericson (Nov 27 2020 at 04:15):

Thanks @Bryan Gin-ge Chen I will try adding an evidence of nonempty set variable in scope.

#### Yakov Pechersky (Nov 27 2020 at 04:15):

The TPIL section there says:

Notice that the declaration variable a : α amounts to the assumption that there is at least one element of type α. This assumption is needed in the second example, as well as in the last two.

#### Lars Ericson (Nov 27 2020 at 04:15):

Thanks @Yakov Pechersky .

#### Lars Ericson (Nov 27 2020 at 16:26):

I am farther along by using `assume`

but stuck on the reverse implication in this proof:

```
open classical
variables (α : Type*) (p q : α → Prop)
variable r : Prop
variable a : α
example : (∃ x, r → p x) ↔ (r → ∃ x, p x) :=
begin
split,
{
intro h,
cases h with x rpx,
assume hr: r,
have px := rpx hr,
constructor,
exact px, -- this works
},
{
intro h,
constructor,
assume hr: r,
have epx := h hr,
cases epx with x px,
exact px, -- this doesn't
},
end
```

The goal state before the second `constructor`

is

```
α : Type u_1,
p : α → Prop,
r : Prop,
h : r → (∃ (x : α), p x)
⊢ ∃ (x : α), r → p x
```

The second `constructor`

eliminates the existential quantifier in `⊢ ∃ (x : α), r → p x`

and leaves behind the `p ?m_1`

. Because the `p ?m_1`

is the result of eliminating an existential, I assume that proving `p x`

for any `x`

should resolve it. The goal state becomes

```
2 goals
α : Type u_1,
p : α → Prop,
r : Prop,
h : r → (∃ (x : α), p x),
hr : r,
x : α,
px : p x
⊢ p ?m_1
α : Type u_1,
p : α → Prop,
r : Prop,
h : r → (∃ (x : α), p x)
⊢ α
```

The `exact px`

results in error

```
invalid type ascription, term has type
p x
but is expected to have type
p ?m_1
```

Any further hints would be greatly appreciated!

#### Kenny Lau (Nov 27 2020 at 16:31):

I think you have to use `variable a : α`

as in your earlier question yesterday.

#### Eric Wieser (Nov 27 2020 at 16:34):

`by_cases r`

I think is the missing step

#### Eric Wieser (Nov 27 2020 at 16:39):

But you also need `include a`

to make the variable available to use

#### Eric Wieser (Nov 27 2020 at 16:40):

I'd recommend you drop this weird `variable a : \a`

stuff and use `[inhabited α]`

+ `default α`

instead

#### Kenny Lau (Nov 27 2020 at 16:40):

I think this is from TPIL or some equivalent book

#### Lars Ericson (Nov 27 2020 at 17:17):

@Kenny Lau the `variable a : α`

is there in the quoted code above. Also yes, this is an exercise in TPIL.

@Eric Wieser thank you for your suggestions, I will try them. Also, in this thread, I was recommended to introduce `variable a : α`

as evidence that `α`

is a non-empty set. I was very firmly corrected for suggesting that there was anything confusing at all about it.

#### Yakov Pechersky (Nov 27 2020 at 17:20):

I think there is some wonkiness to `variable a : α`

and how that gets included in `example`

vs `lemma my_example`

. I think it might have to also do with `include a`

. For the examples where you really need the `a`

, you could write

```
example (a : α) : ...
```

and that would for sure be available.

#### Eric Wieser (Nov 27 2020 at 17:23):

@Yakov Pechersky has hit the nail on the head - `lemma`

determines it's type (which includes its arguments) from the stuff to the left of the `:=`

alone, whereas `def`

/ `example`

look at their definition to work out what they need to pull in as arguments

#### Eric Wieser (Nov 27 2020 at 17:24):

```
variables (x : X)
def foo : some_type := some_value -- means foo (x : X) if `x` is included in either some_type or some_value
```

```
lemma foo' : some_type := some_value -- means foo (x : X) if `x` is included in some_type, ignores some_value
```

#### Bryan Gin-ge Chen (Nov 27 2020 at 17:43):

In TPiL, the need for `include`

is mentioned at the end of Section 5.1 (the first section of the chapter discussing tactics), which I linked yesterday.

By the way, Patrick's point yesterday was not at all to correct you for saying that "there was anything confusing at all about it", but instead that the very different and much more extreme "I just don't think anybody would get it without expert assistance" is not consistent with evidence. Sorry for harping on this, but I believe that if you bring up past conversations, it's important that they are presented accurately.

#### Logan Murphy (Nov 27 2020 at 18:04):

It might also be worth pointing out that some of the confusion is probably coming from the Zulip chat, since at this particular point in TPiL, the reader isn't supposed to know anything about typeclasses or `inhabited`

or `nonempty`

, so the setup presented in the book with the `variable`

trick is pedagogically justifiable, even though it's not how most lean users might state that the type has an element. So when people like myself yesterday respond to Lars' question with "just use a typeclass", it obfuscates the goal of the using the quantifiers correctly.

As opposed to this section of TPiL being particularly hard to navigate

#### Reid Barton (Nov 27 2020 at 18:50):

Eric Wieser said:

Yakov Pechersky has hit the nail on the head -

`lemma`

determines it's type (which includes its arguments) from the stuff to the left of the`:=`

alone, whereas`def`

/`example`

look at their definition to work out what they need to pull in as arguments

Actually regardless of `def`

vs `lemma`

Lean will include any variable mentioned in the proof--but not inside a tactic block because those can't be run until after we know what the type is.

#### Lars Ericson (Nov 27 2020 at 23:50):

Thank you all, I finally got it. I think this uses the smallest number of techniques required to prove this example in tactic mode. I'd love to see a shorter tactic mode proof using fewer kinds of tactics. It definitely requires both the `variable a : α`

and `include a`

to prove this example:

```
variables (α : Type*) (p : α → Prop)
variable r : Prop
variable a : α
include a
example : (∃ x, r → p x) ↔ (r → ∃ x, p x) :=
begin
split,
{
intro h,
cases h with x rpx,
assume hr: r,
have px := rpx hr,
constructor,
exact px,
},
{
intro h,
by_cases hr: r,
have expx := h hr,
cases expx with x rpx,
constructor,
{
intro r_again,
exact rpx,
},
{
by_cases hr1: r,
{
exfalso,
exact hr hr1,
},
{
constructor,
{
intro hr2,
exfalso,
exact hr hr2,
},
exact a,
},
},
},
end
```

#### Eric Wieser (Nov 28 2020 at 00:51):

Your `by_cases hr1`

and the block below it is pointless

#### Eric Wieser (Nov 28 2020 at 00:51):

You already have a proof of r

#### Logan Murphy (Nov 28 2020 at 01:00):

```
example : (∃ x, r → p x) ↔ (r → ∃ x, p x) :=
begin
split, {
rintros ⟨w, H⟩,
intro h_r,
use w, exact H h_r,
},
{
intro h,
by_cases h_r : r,
{ -- case 1 : r
replace h := h h_r,
cases h with w h,
use w, intro _, exact h,},
-- case 2 : not r
use a,
},
end
```

#### Lars Ericson (Nov 28 2020 at 01:31):

@Logan Murphy your proof doesn't go through in the context provided by the "try it!" of section 4.4. It doesn't know `rintros`

or `w`

or `H`

.

Screenshot-from-2020-11-27-20-28-25.png

#### Bryan Gin-ge Chen (Nov 28 2020 at 01:31):

You have to add `import tactic`

at the top since `rintros`

is a tactic from mathlib.

#### Logan Murphy (Nov 28 2020 at 01:53):

Yes, sorry Lars. `rintros`

slightly simplifies regular `intros`

by letting you introduce the witness and proof components of the exisential seperately, rather than having to destruct them manually once they're in the proof context (also applies to other structures beyond existentials) .

#### Lars Ericson (Nov 28 2020 at 01:55):

Thank you @Logan Murphy I'm happy to learn new tactics.

#### Lars Ericson (Nov 28 2020 at 02:54):

Here is another where I want to introduce a `∀`

in tactic mode:

```
import tactic
open classical
variables (α : Type*) (p q : α → Prop)
variable a : α
variable r : Prop
include a
example : (¬ ∀ x, p x) ↔ (∃ x, ¬ p x) :=
begin
split,
{
intro h,
constructor,
intro h1,
sorry,
sorry,
},
{
intro h,
intro hxa,
cases h with x npx,
have px := hxa x,
exact npx px,
},
end
```

Just before the first `sorry`

, the goal state is

```
2 goals
α : Type u_1,
p : α → Prop,
a : α,
h : ¬∀ (x : α), p x,
h1 : p ?m_1
⊢ false
α : Type u_1,
p : α → Prop,
a : α,
h : ¬∀ (x : α), p x
⊢ α
```

We have

`h1 : p ?m_1`

The `?m_1`

is arbitrary. It seems like it should be possible to rewrite this to

`∀ (x : α), p x,`

Is there a tactic or rewrite rule/theorem for this? I couldn't find a `forall.intro`

in mathlib.

#### Logan Murphy (Nov 28 2020 at 03:05):

When you invoke `constructor`

, you have a goal of the form `∃ (x : α), ¬p x`

, so you're breaking it up into two goals, one for the witness and one for the predicate. You haven't told lean what witness to use, hence the metavariable `?m_1`

.

In tactic mode, the more "canonical way" to do this is as follows (using the rewrite tactic `rw`

, which is in chapter 5 of TPil)

```
import tactic
open classical
variables (α : Type*) (p q : α → Prop)
variable a : α
variable r : Prop
include a
example : (¬ ∀ x, p x) ↔ (∃ x, ¬ p x) :=
begin
split,
{
intro h,
rw not_forall at h,
cases h with w h,
existsi w, exact h
},
{
intro h,
intro hxa,
cases h with x npx,
have px := hxa x,
exact npx px,
},
end
```

#### Logan Murphy (Nov 28 2020 at 03:05):

But you haven't "introduced" a `forall`

here, you've just introduced a premise containing a negated `forall`

, which is equivalent to an existential, hence the rewrite.

#### Logan Murphy (Nov 28 2020 at 03:07):

But again, in chapter 4 of TPiL I don't think you're expected to know about tactic mode, hence the rewrite

#### Logan Murphy (Nov 28 2020 at 03:13):

alternatively, rather than using `constructor`

, once you have a witness, you should either use `use`

or, especially for an existential, `existsi`

, which I think is just a more usable tactic version of `exists.intro`

#### Lars Ericson (Nov 28 2020 at 04:29):

Thank you @Logan Murphy . I was using `constructor`

because it is one of the tactics in Chapter 5 that work with quantifiers. `not_forall`

is not mentioned in TPIL. It becomes necessary at this point to start reading the `mathlib`

docs. `rw`

is introduced in the Natural Number Game along with a selection of `rw`

-applicable equivalences from `mathlib`

. `mathlib`

is not mentioned inTPIL.

I guess we kind of come up against the limits of tactic mode around quantifiers. Trying to unpack `not_forall`

leads to term-mode proofs:

```
protected theorem decidable.not_forall {p : α → Prop}
[decidable (∃ x, ¬ p x)] [∀ x, decidable (p x)] : (¬ ∀ x, p x) ↔ ∃ x, ¬ p x :=
⟨not.decidable_imp_symm $ λ nx x, nx.decidable_imp_symm $ λ h, ⟨x, h⟩,
not_forall_of_exists_not⟩
theorem not_forall_of_exists_not : (∃ x, ¬ p x) → ¬ ∀ x, p x
| ⟨x, hn⟩ h := hn (h x)
theorem not.decidable_imp_symm [decidable a] : (¬a → b) → ¬b → a := decidable.not_imp_symm
protected theorem decidable.not_imp_symm [decidable a] (h : ¬a → b) (hb : ¬b) : a :=
decidable.by_contradiction $ hb ∘ h
```

It seems that I should only be using tactic mode up to a certain point and then to really use Lean I have to start thinking in term mode.

#### Marc Huisinga (Nov 28 2020 at 08:58):

Lars Ericson said:

It becomes necessary at this point to start reading the

`mathlib`

docs.

why? you can prove those lemmas without mathlib!

Lars Ericson said:

It seems that I should only be using tactic mode up to a certain point and then to really use Lean I have to start thinking in term mode.

not necessarily, but knowing term mode is useful. mathlib typically uses that style because it's faster and shorter.

#### Marc Huisinga (Nov 28 2020 at 09:04):

i think the left-to-right proof requires classical reasoning, btw.

#### Ruben Van de Velde (Nov 28 2020 at 09:07):

Using `not_forall`

is cheating, that's the lemma you're proving

#### Logan Murphy (Nov 28 2020 at 12:59):

Yes, my bad, you could just do the rewrite and the start and be done

#### Lars Ericson (Nov 28 2020 at 13:26):

I have two questions regarding

```
import tactic
variables (α : Type*) (p : α → Prop)
variable a : α
example : (¬ ∀ x, p x) ↔ (∃ x, ¬ p x) :=
begin
exact not_forall,
end
```

Q1: This doesn't need `open classical`

. Does that mean this doesn't need `em`

, or that `em`

comes with `import tactic`

?

Q2: The type of `not_forall`

is `not_forall {α : Sort u_1} {p : α → Prop}`

. It's not letting me do this:

```
example : (¬ ∀ x, p x) ↔ (∃ x, ¬ p x) := not_forall α p
```

or this

```
example : (¬ ∀ x, p x) ↔ (∃ x, ¬ p x) := not_forall
```

or this

```
example : (¬ ∀ x, p x) ↔ (∃ x, ¬ p x) := exact not_forall α p
```

or this

```
example : (¬ ∀ x, p x) ↔ (∃ x, ¬ p x) := λ {α : Sort u_1}, λ {p : α → Prop}, not_forall α p
```

What is the syntax to apply a theorem in tactic mode in this case?

#### Reid Barton (Nov 28 2020 at 13:27):

Q1: `open`

is just for namespacing

#### Reid Barton (Nov 28 2020 at 13:28):

`open classical`

just means instead of `classical.foo`

you can write `foo`

#### Reid Barton (Nov 28 2020 at 13:30):

Lars Ericson said:

`example : (¬ ∀ x, p x) ↔ (∃ x, ¬ p x) := not_forall`

This one's correct. If it's not working then your setup is not as described.

#### Reid Barton (Nov 28 2020 at 13:34):

`import`

and `open`

and using classical axioms are three unrelated things.

(You have to import an axiom to use it but the ones used for classical logic are automatically imported implicitly.)

#### Marc Huisinga (Nov 28 2020 at 13:41):

Lars Ericson said:

Q1: This doesn't need

`open classical`

. Does that mean this doesn't need`em`

, or that`em`

comes with`import tactic`

?

the proof of `not_forall`

uses classical reasoning, specifically the statement that all propositions are decidable, which turns the statement of `decidable.not_forall`

into `not_forall`

. this is explained at the end of TPIL in chapter 11.

but to prove the statement, you don't need such big guns and can also just use `em`

.

#### Lars Ericson (Nov 28 2020 at 13:43):

@Marc Huisinga that was my question, does it require `em`

. If so does that mean that the theorem is not constructive?

#### Ruben Van de Velde (Nov 28 2020 at 13:44):

Yeah, I believe that's right

#### Marc Huisinga (Nov 28 2020 at 13:44):

yup! the de morgan rules don't hold in full symmetry for constructive logic. three hold, one doesn't.

the exercise also tells you that part of the exercise is to figure out which ones to prove using classical reasoning :)

#### Reid Barton (Nov 28 2020 at 13:45):

You can use `#print axioms not_forall`

to see that it uses `classical.choice`

, which is used to prove excluded middle

#### Lars Ericson (Nov 28 2020 at 13:47):

@Reid Barton thanks for the new command `#print axioms`

. Also, you are right, this works, I don't know why I was having trouble before:

```
import tactic
variables (α : Type*) (p : α → Prop)
example : (¬ ∀ x, p x) ↔ (∃ x, ¬ p x) := not_forall
```

#### Lars Ericson (Nov 28 2020 at 13:55):

So I'm trying to work this out again from scratch. I am starting here, but I have a syntax problem:

```
variables (α : Type*) (p q : α → Prop)
lemma not_forall_implies_exist_not {p : α → Prop} : (¬ ∀ x, p x) ↔ (∃ x, ¬ p x) :=
begin
sorry,
end
#check not_forall_implies_exist_not α -- works
#check not_forall_implies_exist_not α p -- doesn't work
```

It won't let me apply the `lemma`

in the second `check`

. It raises this error:

```
function expected at
not_forall_implies_exist_not α
term has type
(¬∀ (x : α), ?m_1 x) ↔ ∃ (x : α), ¬?m_1 x
```

I am trying to break down my task as follows:

```
example : (¬ ∀ x, p x) ↔ (∃ x, ¬ p x) :=
begin
split,
exact not_forall_implies_exist_not α p,
sorry,
end
```

but I'm stuck on the syntax. I am modelling this after a similar use in Chapter 3, which didn't raise any errors:

```
theorem definition_imply (p q : Prop): (p → q) → (¬p ∨ q) := sorry
theorem imply_definition (p q : Prop): (¬p ∨ q) → (p → q) := sorry
theorem implication (p q : Prop): (¬p ∨ q) ↔ (p → q) :=
begin
split,
exact imply_definition p q,
exact definition_imply p q,
end
```

#### Marc Huisinga (Nov 28 2020 at 13:56):

note the curly brackets

#### Marc Huisinga (Nov 28 2020 at 13:56):

(https://leanprover.github.io/theorem_proving_in_lean/dependent_type_theory.html#implicit-arguments)

#### Lars Ericson (Nov 28 2020 at 14:04):

@Marc Huisinga I don't understand the hint. I have curly brackets in the lemma statement. The form of the statement is exactly like not_forall. However, this doesn't work:

```
import tactic
open classical
variables (α : Type*) (p q : α → Prop)
variable a : α
variable r : Prop
include a
theorem not_forall_implies_exist_not {p : α → Prop} : (¬ ∀ x, p x) ↔ (∃ x, ¬ p x) := sorry
example : (¬ ∀ x, p x) ↔ (∃ x, ¬ p x) :=
begin
split,
exact not_forall_implies_exist_not,
sorry,
end
```

giving error

```
invalid type ascription, term has type
∀ (α : Type ?), α → ∀ {p : α → Prop}, (¬∀ (x : α), p x) ↔ ∃ (x : α), ¬p x
but is expected to have type
(¬∀ (x : α), p x) → (∃ (x : α), ¬p x)
state:
2 goals
α : Type u_1,
p : α → Prop,
a : α
⊢ (¬∀ (x : α), p x) → (∃ (x : α), ¬p x)
α : Type u_1,
p : α → Prop,
a : α
⊢ (∃ (x : α), ¬p x) → (¬∀ (x : α), p x)
```

#### Reid Barton (Nov 28 2020 at 14:05):

I don't understand what you're expecting to achieve by moving the whole statement of the example into a lemma

#### Reid Barton (Nov 28 2020 at 14:06):

since both statements are the same, it's unlikely you can prove one by doing `split`

and then using the other

#### Reid Barton (Nov 28 2020 at 14:06):

I guess you didn't mean to write `↔`

in `not_forall_implies_exist_not`

#### Kevin Buzzard (Nov 28 2020 at 14:08):

@Lars Ericson you should learn to read the error messages. It's getting to the point where you should be able to do this. Many of your recent questions are "why does this not work, the error says "Lean was expecting X but you gave it Y"", and really this is the answer to your question.

#### Kevin Buzzard (Nov 28 2020 at 14:09):

In particular for this question, the error will be on `exact`

, the goal is exactly what X says, what you gave it after the `exact`

is exactly what Y says, and you are asking why it doesn't work.

#### Reid Barton (Nov 28 2020 at 14:17):

Lean is also very sensitive to details and context--I think trying to look at what mathlib does isn't going to help you at this point.

#### Lars Ericson (Nov 28 2020 at 14:24):

@Reid Barton because I am stuck doing it all in one place, I find it helpful to break it down into lemmas for each direction. I know it is the same, but subproceduralizing helps me think.

@Kevin Buzzard I fixed one thing which was I was using `↔`

when I meant `→ `

. However, with this fix, it still doesn't match. This should be fine:

```
import tactic
open classical
variables (α : Type*) (p q : α → Prop)
variable a : α
variable r : Prop
include a
lemma exist_not_implies_not_forall {p : α → Prop} : (∃ x, ¬ p x) → (¬ ∀ x, p x) := sorry
lemma not_forall_implies_exist_not {p : α → Prop} : (¬ ∀ x, p x) → (∃ x, ¬ p x) := sorry
example : (¬ ∀ x, p x) ↔ (∃ x, ¬ p x) :=
begin
split,
exact not_forall_implies_exist_not,
exact exist_not_implies_not_forall,
end
```

but it is giving me this error:

```
invalid type ascription, term has type
∀ (α : Type ?), α → ∀ {p : α → Prop}, (¬∀ (x : α), p x) → (∃ (x : α), ¬p x)
but is expected to have type
(¬∀ (x : α), p x) → (∃ (x : α), ¬p x)
```

If I simplify the example further:

```
import tactic
open classical
variables (α : Type*) (p q : α → Prop)
variable a : α
variable r : Prop
include a
lemma exist_not_implies_not_forall {p : α → Prop} : (∃ x, ¬ p x) → (¬ ∀ x, p x) := sorry
#check exist_not_implies_not_forall -- works
#check exist_not_implies_not_forall α -- works
#check exist_not_implies_not_forall α p -- doesn't work
```

Then the first two `#check`

s work and the third does not, giving error:

```
type mismatch at application
exist_not_implies_not_forall α p
term
p
has type
α → Prop
but is expected to have type
α
```

I do not understand this error message.

#### Reid Barton (Nov 28 2020 at 14:24):

did you see @Marc Huisinga's message above?

#### Reid Barton (Nov 28 2020 at 14:25):

do you know what `{p : α → Prop}`

means?

#### Lars Ericson (Nov 28 2020 at 14:25):

I think it means that `p`

can be inferred and that `p`

has type `α → Prop`

.

#### Kevin Buzzard (Nov 28 2020 at 14:25):

There are three kinds of brackets in Lean. `()`

means "the user supplies this". `{}`

means "The user does not supply this, a system called the unification system will deal with it". And `[]`

means "the user does not supply this, a system called the type class inference system will supply it".

#### Kevin Buzzard (Nov 28 2020 at 14:26):

~~You supplied p, but it was in ~~ (actually, Lean hadn't even got to `{}`

brackets so the system had already supplied it.`p`

yet, as Marc points out)

#### Lars Ericson (Nov 28 2020 at 14:27):

Changing '{}' to '()' I still get an error on the 3rd `#check`

:

```
import tactic
open classical
variables (α : Type*) (p q : α → Prop)
variable a : α
variable r : Prop
include a
lemma exist_not_implies_not_forall (p : α → Prop) : (∃ x, ¬ p x) → (¬ ∀ x, p x) := sorry
#check exist_not_implies_not_forall -- works
#check exist_not_implies_not_forall α -- works
#check exist_not_implies_not_forall α p -- doesn't work
```

The error is

```
type mismatch at application
exist_not_implies_not_forall α p
term
p
has type
α → Prop
but is expected to have type
α
```

#### Marc Huisinga (Nov 28 2020 at 14:27):

this is not actually the problem here @Kevin Buzzard , the problem is the `include a`

.

#### Lars Ericson (Nov 28 2020 at 14:28):

OK removing the `include a`

makes it work and now I am confused.

#### Kevin Buzzard (Nov 28 2020 at 14:28):

I think you should learn the really useful trick `#check @exist_not_implies_not_forall`

. It tells you what all the inputs are.

#### Kevin Buzzard (Nov 28 2020 at 14:28):

You can now remove/add `include a`

and see how the output of that `#check`

changes.

#### Reid Barton (Nov 28 2020 at 14:28):

and, more generally, reading Lean's output rather than thinking in binary "works/doesn't work"

#### Kevin Buzzard (Nov 28 2020 at 14:30):

The `#check @...`

thing was a game-changer for me. I used to struggle with `#check`

. There are some instances when it throws up a very weird error. But adding the `@`

makes everything much clearer.

#### Lars Ericson (Nov 28 2020 at 14:31):

OK without `include a`

```
exist_not_implies_not_forall : ∀ (α : Type u_2) (p : α → Prop), (∃ (x : α), ¬p x) → (¬∀ (x : α), p x)
```

with `include a`

```
exist_not_implies_not_forall : ∀ (α : Type u_2), α → ∀ (p : α → Prop), (∃ (x : α), ¬p x) → (¬∀ (x : α), p x)
```

so in that case it wants `a`

```
#check exist_not_implies_not_forall α a p
```

#### Lars Ericson (Nov 28 2020 at 14:32):

So finally I am home

```
import tactic
open classical
variables (α : Type*) (p q : α → Prop)
variable a : α
variable r : Prop
lemma exist_not_implies_not_forall (p : α → Prop) : (∃ x, ¬ p x) → (¬ ∀ x, p x) := sorry
lemma not_forall_implies_exist_not (p : α → Prop) : (¬ ∀ x, p x) → (∃ x, ¬ p x) := sorry
example : (¬ ∀ x, p x) ↔ (∃ x, ¬ p x) :=
begin
split,
exact not_forall_implies_exist_not α p,
exact exist_not_implies_not_forall α p,
end
```

#### Reid Barton (Nov 28 2020 at 14:33):

You could delete `variable a : α`

too, since it's not needed for this theorem

#### Marc Huisinga (Nov 28 2020 at 14:34):

@Lars Ericson by writing `include a`

, you made `a : α`

a parameter to `exist_not_implies_not_forall`

.

to repeat some stuff from TPIL:

`variable (foo : bar)`

means that all the following definitions will take (foo : bar) as argument *if* `foo`

is used either in the signature of the `def`

or the *term* of the `def`

supplied after `:=`

.

for technical reasons, this doesn't work well if the term after `:=`

is supplied in tactic mode (explained in section 5.1), so you need to tell lean explicitly to make it a parameter, using `include`

.

#### Marc Huisinga (Nov 28 2020 at 14:36):

unfortunately, in this case you did not actually want it as a parameter :)

#### Mario Carneiro (Nov 28 2020 at 15:15):

Kevin Buzzard said:

There are three kinds of brackets in Lean.

`()`

means "the user supplies this".`{}`

means "The user does not supply this, a system called the unification system will deal with it". And`[]`

means "the user does not supply this, a system called the type class inference system will supply it".

There are actually five. Number four is `{{}}`

aka `⦃⦄`

, which means that they are not supplied by the user, and the system only inserts them if other arguments after are inserted by the user, and number five is `aux_decl`

which has no user level syntax and is used to insert the fake signature of a recursive function inside its own body, as well as to compile matches and destructuring lets (you might have seen things in the context called `_match`

and `_let_match`

before).

#### Mario Carneiro (Nov 28 2020 at 15:16):

/me takes off pedant hat

#### Marc Huisinga (Nov 28 2020 at 15:18):

lean4 now also has the ` `

brackets: https://github.com/leanprover/lean4/blob/master/src/Init/System/IO.lean#L31

#### Reid Barton (Nov 28 2020 at 15:33):

I can't figure out what this is referring to

#### Marc Huisinga (Nov 28 2020 at 15:35):

`ε`

and `α`

are not quantified at all

#### Eric Wieser (Nov 28 2020 at 15:35):

Wasn't there another type of bracket like `(+ ... +)`

which gives a hint to the simplifier?

#### Mario Carneiro (Nov 28 2020 at 15:40):

Ah, you are thinking of `(: ... :)`

which is a hint to the e-matcher

#### Lars Ericson (Nov 28 2020 at 15:40):

@Mario Carneiro can you show me how to use `let`

and `match`

inside a `begin end`

? `match`

has its own `end`

. Chapter 4 doesn't have an example of use of `let`

or `match`

inside a tactic-mode `begin end`

proof.

#### Mario Carneiro (Nov 28 2020 at 15:41):

There is a tactic called `let`

, you can use it just like `have`

#### Mario Carneiro (Nov 28 2020 at 15:41):

there is no `match`

tactic, but `rcases`

does most of what `match`

can do

#### Mario Carneiro (Nov 28 2020 at 15:45):

@Eric Wieser `(: ... :)`

isn't actually a binder, it surrounds a *subterm* of an expression, and I'm not sure exactly how it's encoded, probably as a macro

#### Lars Ericson (Nov 28 2020 at 16:13):

@Mario Carneiro as one of my subgoals I have re-proved this:

```
theorem foo1 {b : Prop}: ((∃ x, p x) → b) → ∀ x, p x → b :=
λ h x hpx, h ⟨x, hpx⟩
```

with this tactic-mode proof:

```
theorem foo1 {b : Prop}: ((∃ x, p x) → b) → ∀ x, p x → b :=
begin
intro h1,
assume x,
intro h2,
exact h1 (exists.intro x h2),
end
```

Is there a more elegant purely tactic-mode proof which uses `let`

or `rcases`

?

#### Mario Carneiro (Nov 28 2020 at 16:42):

there is no let or match in the term proof either

#### Mario Carneiro (Nov 28 2020 at 16:43):

you can replace the `intro assume intro`

with just `intros h1 x h2`

but if a proof is just `intros, exact`

then there isn't really a point in using tactic mode

#### Lars Ericson (Nov 28 2020 at 17:13):

I would like to dig into `not_forall`

and pull out one side of it. The definition below of `my_not_forall`

is exactly like not_forall:

```
import tactic
open classical
variables {α : Sort*} {β : Sort*} {p q : α → Prop} {b : Prop}
#check α -- gives α : Sort u_1
#check not_forall -- gives not_forall : (¬∀ (x : ?M_1), ?M_2 x) ↔ ∃ (x : ?M_1), ¬?M_2 x
#check decidable.not_forall -- gives decidable.not_forall : (¬∀ (x : ?M_1), ?M_2 x) ↔ ∃ (x : ?M_1), ¬?M_2 x
theorem my_not_forall: (¬ ∀ x, ¬ p x) ↔ ∃ x, p x := decidable.not_forall_not
```

however I am getting error

```
Display GoalDisplay Messages
10:52: error:
failed to synthesize type class instance for
α : Sort u_1,
p : α → Prop
⊢ decidable (∃ (x : α), p x)
```

It seems I am missing a `decidable`

constructor which gets inferred when it is in `mathlib`

but not here? Is there a way to fix this? I really want to get down to this part:

```
not.decidable_imp_symm $ λ nx x, nx.decidable_imp_symm $ λ h, ⟨x, h⟩
```

of

```
theorem decidable.not_forall {p : α → Prop}
[decidable (∃ x, ¬ p x)] [∀ x, decidable (p x)] : (¬ ∀ x, p x) ↔ ∃ x, ¬ p x :=
⟨not.decidable_imp_symm $ λ nx x, nx.decidable_imp_symm $ λ h, ⟨x, h⟩,
not_forall_of_exists_not⟩
```

but it seems like I need to wrap things with `decidable`

constructor at some point to get down into `not.decidable_imp_symm`

and `nx.decidable_imp_symm `

.

#### Marc Huisinga (Nov 28 2020 at 17:24):

you might want to try to prove it regularly instead and wait with this until you've read chapter 11. the mathlib proof uses an attribute that makes all propositions decidable (as a result of em).

trying to do this with typeclasses and decidability should be very confusing if you haven't read the corresponding sections.

#### Lars Ericson (Nov 28 2020 at 17:37):

Thanks @Marc Huisinga I am stuck here:

```
import tactic
open classical
variables {α : Sort*} {β : Sort*} {p q : α → Prop} {b : Prop}
variable a : α
include a
lemma not_forall_implies_exist_not (p : α → Prop) : (¬ ∀ x, p x) → (∃ x, ¬ p x) :=
begin
intro h1,
by_contra h2,
apply h2,
use a,
intro h3,
sorry,
end
```

with goal state

```
α : Sort u_1,
a : α,
p : α → Prop,
h1 : ¬∀ (x : α), p x,
h2 : ¬∃ (x : α), ¬p x,
h3 : p a
⊢ false
```

I will wait on this `sorry`

until after Chapter 11.

#### Mario Carneiro (Nov 28 2020 at 17:41):

don't use `a`

, it's a red herring

#### Mario Carneiro (Nov 28 2020 at 17:43):

You have two things in your context that imply `false`

. One of them will get you more or less back to where you started, so try the other one

#### Johan Commelin (Nov 28 2020 at 17:45):

```
by_contra foobar,
apply foobar
```

is basically doing nothing.

#### Marc Huisinga (Nov 28 2020 at 17:49):

here's another hint (not the full proof, but close):

#### Lars Ericson (Nov 28 2020 at 17:58):

I looked in TPIL again and it actually spells out the proof in term mode, I just have to understand this and maybe term-mode-ify it for extra self-brownie-points. This is what is done inside `mathlib`

, the `r`

is unified with `false`

. **Note**: This uses and requires the red herring:

```
import tactic
open classical
variables (α : Type*) (p q : α → Prop)
variable a : α
variable r : Prop
example : ((∀ x, p x) → r) → (∃ x, p x → r) :=
assume h1 : (∀ x, p x) → r,
show ∃ x, p x → r, from
by_cases
(assume hap : ∀ x, p x, ⟨a, λ h', h1 hap⟩)
(assume hnap : ¬ ∀ x, p x,
by_contra
(assume hnex : ¬ ∃ x, p x → r,
have hap : ∀ x, p x, from
assume x,
by_contra
(assume hnp : ¬ p x,
have hex : ∃ x, p x → r,
from ⟨x, (assume hp, absurd hp hnp)⟩,
show false, from hnex hex),
show false, from hnap hap))
```

#### Lars Ericson (Nov 28 2020 at 18:00):

This proof uses 10 levels of indents/abstraction to get it done. I don't know if it can be done in fewer levels.

#### Mario Carneiro (Nov 28 2020 at 18:15):

yeah, don't use term mode and it will solve your indent problem

#### Mario Carneiro (Nov 28 2020 at 18:16):

I can tell you that you don't need three choicy things (by_cases, by_contra, by_contra)

#### Mario Carneiro (Nov 28 2020 at 18:22):

The proof in mathlib doesn't look like this at all, it doesn't use the implies r version

#### Mario Carneiro (Nov 28 2020 at 18:23):

```
protected theorem decidable.not_forall {p : α → Prop}
[decidable (∃ x, ¬ p x)] [∀ x, decidable (p x)] : (¬ ∀ x, p x) ↔ ∃ x, ¬ p x :=
⟨not.decidable_imp_symm $ λ nx x, nx.decidable_imp_symm $ λ h, ⟨x, h⟩,
not_forall_of_exists_not⟩
```

#### Marc Huisinga (Nov 28 2020 at 18:29):

(also, the `((∀ x, p x) → r) → (∃ x, p x → r)`

proof is much trickier than what you want to prove!)

#### Lars Ericson (Nov 28 2020 at 20:29):

Letting the code in TPIL and NNG do most of the work, I got this proof, but the ending is weird:

```
import tactic
open classical
variables (α : Type*) (p q : α → Prop)
variable a : α
variable r : Prop
include a
include r
example : (∃ x, p x → r) → (∀ x, p x) → r :=
assume ⟨b, (hb : p b → r)⟩,
assume h2 : ∀ x, p x,
show r, from hb (h2 b)
theorem aprf_to_eprf : ((∀ x, p x) → false) → (∃ x, p x → false) :=
assume h1 : (∀ x, p x) → false,
show ∃ x, p x → false, from
by_cases
(assume hap : ∀ x, p x, ⟨a, λ h', h1 hap⟩)
(assume hnap : ¬ ∀ x, p x,
by_contra
(assume hnex : ¬ ∃ x, p x → false,
have hap : ∀ x, p x, from
assume x,
by_contra
(assume hnp : ¬ p x,
have hex : ∃ x, p x → false,
from ⟨x, (assume hp, absurd hp hnp)⟩,
show false, from hnex hex),
show false, from hnap hap))
lemma not_iff_imp_false (P : Prop) : ¬ P ↔ P → false := iff.rfl
lemma not_forall_implies_exist_not (p : α → Prop) : (¬ ∀ x, p x) → (∃ x, ¬ p x) :=
begin
intro h1,
rw not_iff_imp_false at h1,
have h2 := aprf_to_eprf α p a r h1,
cases h2 with x pxf,
rw ← not_iff_imp_false at pxf,
exact exists.intro x pxf,
exact α,
exact r,
exact α,
exact r,
end
```

#### Marc Huisinga (Nov 28 2020 at 20:44):

@Lars Ericson can you prove it from my hint? if not, i can give you one more step :)

#### Lars Ericson (Nov 28 2020 at 20:47):

@Marc Huisinga here is my whole proof for the original exercise. I will go back and look harder at your hint now. Don't give me the extra step yet. Note my setup leads to a proof with some strange artifacts like having to say

```
exact α,
exact r,
exact α,
exact r,
```

and invoke with lots of arguments`exact not_forall_implies_exist_not α a r p`

:

```
import tactic
open classical
variables (α : Type*) (p q : α → Prop)
variable a : α
variable r : Prop
include a
include r
theorem apxf_to_epxf : ((∀ x, p x) → false) → (∃ x, p x → false) :=
assume h1 : (∀ x, p x) → false,
show ∃ x, p x → false, from
by_cases
(assume hap : ∀ x, p x, ⟨a, λ h', h1 hap⟩)
(assume hnap : ¬ ∀ x, p x,
by_contra
(assume hnex : ¬ ∃ x, p x → false,
have hap : ∀ x, p x, from
assume x,
by_contra
(assume hnp : ¬ p x,
have hex : ∃ x, p x → false,
from ⟨x, (assume hp, absurd hp hnp)⟩,
show false, from hnex hex),
show false, from hnap hap))
lemma not_iff_imp_false (P : Prop) : ¬ P ↔ P → false := iff.rfl
lemma not_forall_implies_exist_not (p : α → Prop) : (¬ ∀ x, p x) → (∃ x, ¬ p x) :=
begin
intro h1,
rw not_iff_imp_false at h1,
have h2 := apxf_to_epxf α p a r h1,
cases h2 with x pxf,
rw ← not_iff_imp_false at pxf,
exact exists.intro x pxf,
exact α,
exact r,
exact α,
exact r,
end
lemma exist_not_implies_not_forall (p : α → Prop) : (∃ x, ¬ p x) → (¬ ∀ x, p x) :=
begin
intro h,
intro h1,
cases h with x npx,
have h2 := h1 x,
exact npx h2,
end
example : (¬ ∀ x, p x) ↔ (∃ x, ¬ p x) :=
begin
split,
exact not_forall_implies_exist_not α a r p,
exact exist_not_implies_not_forall α a r p,
end
```

#### Marc Huisinga (Nov 28 2020 at 20:56):

btw:

```
import tactic
open classical
variables (α : Type*) (p : α → Prop)
variable a : α
include a
theorem apxf_to_epxf : ((∀ x, p x) → false) → (∃ x, p x → false) :=
assume h1 : (∀ x, p x) → false,
show ∃ x, p x → false, from
by_cases
(assume hap : ∀ x, p x, ⟨a, λ h', h1 hap⟩)
(assume hnap : ¬ ∀ x, p x,
by_contra
(assume hnex : ¬ ∃ x, p x → false,
have hap : ∀ x, p x, from
assume x,
by_contra
(assume hnp : ¬ p x,
have hex : ∃ x, p x → false,
from ⟨x, (assume hp, absurd hp hnp)⟩,
show false, from hnex hex),
show false, from hnap hap))
lemma not_forall_implies_exist_not (p : α → Prop) : (¬ ∀ x, p x) → (∃ x, ¬ p x) :=
apxf_to_epxf _ _ a
```

#### Lars Ericson (Nov 28 2020 at 21:06):

Thanks @Marc Huisinga . What is the extra hint? I only got this far with the first hint and I'm stuck:

```
lemma not_forall_implies_exist_not2 (p : α → Prop) : (¬ ∀ x, p x) → (∃ x, ¬ p x) :=
begin
intro h1,
by_contra h2,
apply h1,
intro x,
-- we'd really like to use h2 now. we already have an x! how could we get ¬p x?
exfalso,
apply h2,
use x,
intro h3,
apply h2,
sorry,
end
```

#### Marc Huisinga (Nov 28 2020 at 21:08):

one thing you need to learn for these kinds of proofs is when something you're trying to do is a bad idea.

for instance, if you're looping it's a bad idea. or using `by_contra h, apply h`

. in this case you're destroying perfectly fine context information with `exfalso`

!

#### Kevin Buzzard (Nov 28 2020 at 21:09):

Actually `finish`

still works after `exfalso`

;-)

#### Marc Huisinga (Nov 28 2020 at 21:10):

@Kevin Buzzard that doesn't surprise me at all, given that you've still got h1 and h2.

#### Marc Huisinga (Nov 28 2020 at 21:11):

@Lars Ericson could you maybe do something other than `exfalso`

to get `¬p x`

?

#### Lars Ericson (Nov 28 2020 at 21:33):

Thanks @Marc Huisinga I got it:

```
import tactic
open classical
variables (α : Type*) (p : α → Prop)
theorem negneg (p : Prop) : ¬¬p → p :=
begin
intro h,
by_contra h1,
exact h h1,
end
lemma not_forall_implies_exist_not2 (p : α → Prop) : (¬ ∀ x, p x) → (∃ x, ¬ p x) :=
begin
intro h1,
by_contra h2,
apply h1,
intro x,
by_cases h3: ¬p x,
have h4 := exists.intro x h3,
exfalso,
exact h2 h4,
exact negneg (p x) h3,
end
```

#### Marc Huisinga (Nov 28 2020 at 21:40):

shorter (without the cumbersome double-negation departure that you could have also avoided had you done `by_cases h3 : p x`

instead):

```
lemma not_forall_implies_exist_not (p : α → Prop) : (¬ ∀ x, p x) → (∃ x, ¬ p x) :=
begin
intro h1,
by_contra h2,
apply h1,
intro x,
by_contra h,
exact h2 ⟨x, h⟩
end
```

#### Marc Huisinga (Nov 28 2020 at 21:41):

term mode:

```
lemma not_forall_implies_exist_not' (p : α → Prop) : (¬ ∀ x, p x) → (∃ x, ¬ p x) :=
λ h1, by_contradiction (λ h2, h1 (λ x, by_contradiction (λ h, h2 ⟨x, h⟩)))
```

Last updated: Dec 20 2023 at 11:08 UTC