Zulip Chat Archive

Stream: new members

Topic: Higher order chaos


Ken Roe (Jul 14 2018 at 23:25):

I was experimenting with lambda reductions. Can someone help me complete the following theorem:

theorem testit: ( x, ((λ (f : (  )), (λ (x:), (f x)+(f x)))
                         (λ (x:), x+1)) x = 1)  3=4 :=
begin
    intro, cases a,sorry
end

What should replace the "sorry"?

Mario Carneiro (Jul 14 2018 at 23:35):

here's a proof:

theorem testit: (∃ x, ((λ (f : (ℕ → ℕ)), (λ (x:ℕ), (f x)+(f x)))
                         (λ (x:ℕ), x+1)) x = 1) → 3=4 :=
begin
    intro, cases a,
    dsimp at a_h,
    rw [add_assoc, add_left_comm 1] at a_h,
    cases a_h
end

Kevin Buzzard (Jul 15 2018 at 10:01):

Here's a more fleshed-out argument:

theorem testit: ( x, ((λ (f : (  )), (λ (x:), (f x)+(f x)))
                         (λ (x:), x+1)) x = 1)  3=4 :=
begin
    intro, cases a with n Hn, -- name the hypotheses
    exfalso, -- we're going to prove by contradiction
    change (n + 1) + (n + 1) = 1 at Hn, -- instead of dsimp do the definitional rewrite yourself
    rw add_assoc at Hn, -- Hn now n + 1 + n + 1 = 1
    rw add_right_comm n at Hn, -- Hn now (n + n) + 1 + 1 = 1
    have H₂ := nat.succ.inj Hn, -- H₂ now (n+n)+1=0
    exact nat.succ_ne_zero _ H₂,
end

Kenny Lau (Jul 15 2018 at 10:11):

theorem testit: ( x, ((λ (f : (  )), (λ (x:), (f x)+(f x)))
                         (λ (x:), x+1)) x = 1)  3=4 :=
λ x, h, nat.cases_on x
  (λ H, nat.no_confusion $ nat.succ_inj H)
  (λ n H, nat.no_confusion $ nat.succ_inj H) h

theorem testit': ( x, ((λ (f : (  )), (λ (x:), (f x)+(f x)))
                         (λ (x:), x+1)) x = 1)  3=4 :=
λ x, h, by cases x; from nat.no_confusion (nat.succ_inj h)

theorem testit'': ( x, ((λ (f : (  )), (λ (x:), (f x)+(f x)))
                         (λ (x:), x+1)) x = 1)  3=4
| 0, h := nat.no_confusion (nat.succ_inj h)

Patrick Massot (Jul 15 2018 at 10:11):

Now let's go for a more mathlib version:

import tactic.ring

theorem testit: ( x, ((λ (f : (  )), (λ (x:), (f x)+(f x)))
                         (λ (x:), x+1)) x = 1)  3=4 :=
begin
    rintro n, Hn, -- name the hypotheses
    by_contradiction, -- we're going to prove by contradiction
    change (n + 1) + (n + 1) = 1 at Hn, -- instead of dsimp do the definitional rewrite yourself
    rw (show (n + 1) + (n + 1) = 2*n+2, by ring) at Hn,
    have H₂ := nat.succ.inj Hn, -- H₂ now 2*n+1=0
    exact nat.succ_ne_zero _ H₂,
end

Kenny Lau (Jul 15 2018 at 10:11):

I believe my last version would be the mathlib version :P

Patrick Massot (Jul 15 2018 at 10:12):

I meant using mathlib tactics. Note the use of rintro to squash Kevin's first two lines into one, and the use of ring for the computation

Kenny Lau (Jul 15 2018 at 10:13):

obfuscated version:

theorem testit'': ( x, ((λ (f : (  )), (λ (x:), (f x)+(f x)))
                         (λ (x:), x+1)) x = 1)  3=4
| 0, h := congr_arg ((+)2) h.symm

Patrick Massot (Jul 15 2018 at 10:13):

I also replaced exfalso by by_contradiction. Here it buys you nothing but it's more powerful in general, so let's remember that one.

Mario Carneiro (Jul 15 2018 at 10:16):

I prefer:

theorem testit'': (∃ x, ((λ (f : (ℕ → ℕ)), (λ (x:ℕ), (f x)+(f x)))
                         (λ (x:ℕ), x+1)) x = 1) → 3=4
| ⟨0, h⟩ := by cases h

Kenny Lau (Jul 15 2018 at 10:17):

nice

Mario Carneiro (Jul 15 2018 at 10:17):

the match against 0 at the beginning is clever

Mario Carneiro (Jul 15 2018 at 10:18):

(but of course none of these is the mathlib version because the statement is ridiculous)

Patrick Massot (Jul 15 2018 at 10:19):

Again, my "mathlib version" story was only about rewriting Kevin's proof in the same spirit but using more mathlib power

Patrick Massot (Jul 15 2018 at 10:19):

Anyway, hopefully Ken will be able to learn many things from this discussion

Mario Carneiro (Jul 15 2018 at 10:20):

I think lean golf is a nice way to learn new tricks, although its actual applicability is debatable

Patrick Massot (Jul 15 2018 at 10:20):

Actually I'd like to be sure I understand your trick. You let the equation compiler do the job of checking that 0 is the only possibility for x, right?

Kenny Lau (Jul 15 2018 at 10:22):

import logic.basic

theorem testit: ( x, ((λ (f : (  )), (λ (x:), (f x)+(f x)))
                         (λ (x:), x+1)) x = 1)  3=4 :=
by simp; intros x H; cases H

Mario Carneiro (Jul 15 2018 at 10:22):

Right. The equation compiler figures out a sequence of case splits that produce the cases that I give. Since I wrote 0 instead of n for the first thing, it deduces that we have a case split on the nat, but that requires a second branch, for <succ n, h>. But here h has a type like succ stuff = 0, so it does a second case split on h and deduces that this case is impossible

Patrick Massot (Jul 15 2018 at 10:23):

Ok, this is what I thought. Well done, equation compiler!

Mario Carneiro (Jul 15 2018 at 10:24):

I like to take advantage of this for doing things like pattern matching on l : list A and h : length l = 2 and only providing a case for [a, b], _

Kenny Lau (Jul 15 2018 at 10:24):

theorem testit: ( x, ((λ (f : (  )), (λ (x:), (f x)+(f x)))
                         (λ (x:), x+1)) x = 1)  3=4 :=
λ x, H, by simp at H; cases H

Kevin Buzzard (Jul 15 2018 at 10:26):

I like the way that the title of this thread was once a bit of an overstatement but has now become true. Something here for everyone now :-)

Kevin Buzzard (Jul 15 2018 at 10:37):

Actually I'd like to be sure I understand your trick.

I'm still struggling with the cases a_h line in the very first proof :rolling_on_the_floor_laughing:

cases seems to be much more powerful than I'd realised. Applied to n + (n + (1 + 1)) = 1 it realises that both nats are succ (something) so reduces to succ (n+n)=0 and then tries again, realises that the nats are made with different constructors this time, and solves the goal. At least that's my understanding of what's going on.

Kevin Buzzard (Jul 15 2018 at 10:42):

theorem testit: ( x, ((λ (f : (  )), (λ (x:), (f x)+(f x)))
                         (λ (x:), x+1)) x = 1)  3=4 :=
λ x, H, by simp at H; cases H

You lose a point for proof instability

Kevin Buzzard (Jul 15 2018 at 10:42):

When Leo removes add_assoc from simp you're in trouble

Kenny Lau (Jul 15 2018 at 10:42):

you sound like Mario

Kevin Buzzard (Jul 15 2018 at 10:42):

I'm practising.

Kenny Lau (Jul 15 2018 at 10:43):

theorem testit: ( x, ((λ (f : (  )), (λ (x:), (f x)+(f x)))
                         (λ (x:), x+1)) x = 1)  3=4 :=
λ x, H, by cases x; injections

Kevin Buzzard (Jul 15 2018 at 10:45):

theorem testit4: ( x, ((λ (f : (  )), (λ (x:), (f x)+(f x)))
                         (λ (x:), x+1)) x = 1)  3=4
| 0, H := by injections

Mario Carneiro (Jul 15 2018 at 10:45):

yes, cases basically has injection built in

Kevin Buzzard (Jul 15 2018 at 10:45):

I don't think I'd internalised that before.

Mario Carneiro (Jul 15 2018 at 10:46):

That's what makes doing cases on an inductive predicate so powerful (like Coq's inversion tactic)

Mario Carneiro (Jul 15 2018 at 10:46):

because it can skip all the cases where the indices don't match up

Kevin Buzzard (Jul 15 2018 at 10:47):

That's funny, because last week my son discovered this. IIRC inversion is introduced in Software Foundations well after cases and in Lean you can just do cases anyway. I think that when I did those exercises in Lean myself I was still at the "let's try cases;simp and see if it works" stage.

Kevin Buzzard (Jul 15 2018 at 10:50):

In my experiments trying to understand cases on eq I found that it could be used to do a rewrite for either the left or the right hand side (cases a = blah and cases blah = a both remove a and substitute blah everywhere). The only disconcerting thing is that the order of the hypotheses gets randomised a bit (presumably because they're reverted and then unreverted under the hood or something)


Last updated: Dec 20 2023 at 11:08 UTC