Zulip Chat Archive

Stream: Berkeley Lean Seminar

Topic: Two silly questions


Rahul Dalal (Jun 09 2020 at 20:12):

What is the difference between passing in something like "function \< a b \> " and just doing "function a b"

Related to this, what exactly is rintro \<a b\> doing? What does it mean when one of those is replaced with rfl?

Kevin Buzzard (Jun 09 2020 at 20:13):

\<a, b\> is one term, and a b is two.

Kevin Buzzard (Jun 09 2020 at 20:14):

Sometimes you want to deal with the type of natural numbers less than nn. In Lean this is the "canonical set of size nn" and it's denoted fin n.

Kevin Buzzard (Jun 09 2020 at 20:16):

A term of type fin n is two things: a natural number mm, and a proof that m<nm<n. The way I thought about such a concept for decades was that mm was a number and the proof that m<nm<n was a proof, and that numbers and proofs were entirely different things. An interesting consequence of doing maths in Type theory rather than set theory is that mm is a term, and a proof that m<nm<n is also a term.

Kevin Buzzard (Jun 09 2020 at 20:18):

So a term of type fin n is a package of data, consisting both of m and the proof that m<n. In particular if a : fin n then a is not a natural number.

Kevin Buzzard (Jun 09 2020 at 20:19):

So given that a is some kind of package of data, one has to know how to get to m and the proof.

Kevin Buzzard (Jun 09 2020 at 20:21):

To figure out how to do this, we need to look at the definition of fin n by typing something like #check fin and then right clicking on fin and peeking at the definition. We find that fin n is defined to be a structure, which means an inductive type with one constructor.

Kevin Buzzard (Jun 09 2020 at 20:21):

structure fin (n : nat) :=
(val : nat)
(is_lt : val < n)

Kevin Buzzard (Jun 09 2020 at 20:21):

So if a : fin n then a.val will be the mm above, and a.is_lt will be the proof that it's less than nn.

Kevin Buzzard (Jun 09 2020 at 20:23):

example :  (x : fin 10),  m, m < 10 :=
begin
  sorry
end

In this example, the claim is that for every x of type fin 10 we can find an m such that m<10. Note that m=x won't do, because x isn't a natural number, despite the fact that sometimes people will refer to xx as "a natural number less than 10". It's not that, it's a term of type fin 10 so it's a pair.

Kevin Buzzard (Jun 09 2020 at 20:24):

import tactic -- I always do this

example :  (x : fin 10),  m, m < 10 :=
begin
  intro x,
  /-
  x : fin 10
  ⊢ ∃ (m : ℕ), m < 10
  -/
  use x.val,
  /-
  x : fin 10
  ⊢ x.val < 10
  -/
  exact x.is_lt
end

Kevin Buzzard (Jun 09 2020 at 20:25):

The natural number we use is x.val, and the proof it satisfies the right thing is x.is_lt.

Kevin Buzzard (Jun 09 2020 at 20:26):

Another way of getting the terms out of a structure is to use the cases command.

import tactic -- I always do this

example :  (x : fin 10),  m, m < 10 :=
begin
  intro x,
  cases x with m hm,
  /-
  m : ℕ,
  hm : m < 10
  ⊢ ∃ (m : ℕ), m < 10
  -/
  use m,
  exact hm
end

Kevin Buzzard (Jun 09 2020 at 20:28):

cases is a core Lean tactic. Sometimes structures are fancier objects though, with 3 or more fields, or fields containing other structures, and so the rcases tactic was born, which can take more complex structures apart. For this the standard cases syntax of just listing variable names wasn't powerful enough, so they started with these pointy brackets.

import tactic -- I always do this

example :  (x : fin 10),  m, m < 10 :=
begin
  intro x,
  rcases x with m, hm,
  use m,
  exact hm
end

Kevin Buzzard (Jun 09 2020 at 20:29):

intro, rcases was such a common idiom that rintro was born:

example :  (x : fin 10),  m, m < 10 :=
begin
  rintro m, hm,
  use m,
  exact hm
end

Kevin Buzzard (Jun 09 2020 at 20:29):

This introduces x and then instantly takes it apart into its pieces.

Kevin Buzzard (Jun 09 2020 at 20:31):

Here's a silly structure:

import tactic -- I always do this

structure silly :=
(n : )
(b : bool)
(m : )
(h : n < 37)
(hmn : m = n)

example :  x : silly, x.m < 37 :=
begin
  sorry
end

Kevin Buzzard (Jun 09 2020 at 20:31):

To make a term of type silly you need to supply two naturals, a boolean, a proof that the two naturals are equal, and a proof that one of the naturals is less than 37.

Rahul Dalal (Jun 09 2020 at 20:32):

Thank you!

Kevin Buzzard (Jun 09 2020 at 20:33):

Using our rintro skills we can solve this example as follows:

example :  x : silly, x.m < 37 :=
begin
  rintro n, b, m, h, hnm,
  -- goal is now a mess
  dsimp,
  /-
  n : ℕ,
  b : bool,
  m : ℕ,
  h : n < 37,
  hnm : m = n
  ⊢ m < 37
  -/
  rw hnm,
  -- ⊢ n < 37
  exact h,
end

Kevin Buzzard (Jun 09 2020 at 20:34):

(dsimp simplifies {m := blah, ... }.m to blah)

Kevin Buzzard (Jun 09 2020 at 20:35):

But rintro has got one more trick up its sleeve -- instead of rintroing hnm we can put rfl instead, which just means "define one side to be the other side".

Kevin Buzzard (Jun 09 2020 at 20:36):

example :  x : silly, x.m < 37 :=
begin
  rintro ⟨_, b, m, h, rfl,
  -- h is now a proof of m<37!
  exact h,
end

Kevin Buzzard (Jun 09 2020 at 20:36):

tactic#rintro

Rahul Dalal (Jun 09 2020 at 20:43):

So practically, you can put rfl in any spot where the corresponding term is an equality or equivalence and it will apply this to everything other term you are creating in the rintro?

Kevin Buzzard (Jun 09 2020 at 20:43):

I'm not sure about an equivalence but yes an equality

Kevin Buzzard (Jun 09 2020 at 20:44):

It will look to see if one side or the other is a bare variable, and if one of them is then it will basically just sub in its value everywhere

Kevin Buzzard (Jun 09 2020 at 20:44):

What it's actually doing is cases h if h : a = b!

Kevin Buzzard (Jun 09 2020 at 20:45):

Because = is not a primitive notion in type theory, it's notation for eq which is an inductive type with one constructor, just like silly

Kevin Buzzard (Jun 09 2020 at 20:46):

eq a b is an inductive type with one constructor, refl a which is a term of type eq a a (note I just corrected a bad typo here)

Kevin Buzzard (Jun 09 2020 at 20:47):

If you work out the recursor for that type, it's the principle that if you know P(a) and you know that a=b, you can deduce P(b)

Kevin Buzzard (Jun 09 2020 at 20:48):

Ie it's the fact that you can substitute in an equality

Kevin Buzzard (Jun 09 2020 at 20:48):

This is the basic principle behind the rewrite tactic

Rahul Dalal (Jun 09 2020 at 20:58):

ok, thanks again!


Last updated: Dec 20 2023 at 11:08 UTC