Zulip Chat Archive

Stream: Is there code for X?

Topic: function.injective fin


Eric Wieser (Nov 15 2021 at 12:26):

Is there a way of proving this earlier in the import heirarchy?

import data.fin.basic
import data.fintype.basic

lemma fin_injective : function.injective fin :=
λ m n h,
  (fintype.card_fin m).symm.trans $ (fintype.card_congr $ equiv.cast h).trans (fintype.card_fin n)

In particular, I'd like to state docs#fin.cast_eq_cast in reverse so that any docs#cast of fin can be turned into a docs#fin.cast

Eric Rodriguez (Nov 15 2021 at 13:03):

I have to go cook, but will something like this work?

import data.fin.basic

lemma fin_injective : function.injective fin :=
begin
  intros m n h,
  --simp only [fin] at h,
  cases m; cases n,
  { refl },
  { have hn := n.succ_pos,
    rw fin.pos_iff_nonempty at hn,
    have := hn.some,
    rw h at this,
    exact fin_zero_elim this },
  { have hm := m.succ_pos,
    rw fin.pos_iff_nonempty at hm,
    have := hm.some,
    rw h at this,
    exact fin_zero_elim this },
  { have := fin.last_val m,
    have := fin.last_val n,
    sorry }
end

Also, what do you mean about fin.cast_eq_cast in reverse?

Yakov Pechersky (Nov 15 2021 at 13:09):

Can you use the fact that fin.cast is a nonsurjective embedding? Going through lt_trichotomy n m.

Eric Wieser (Nov 15 2021 at 13:28):

Eric Rodriguez said:

Also, what do you mean about fin.cast_eq_cast in reverse?

I mean

theorem fin.cast_eq_cast' {n m : } (h : fin n = fin m) :
  cast h = (fin.cast $ fin_injective h) :=
(fin.cast_eq_cast _).symm

Reid Barton (Nov 15 2021 at 13:33):

It seems like the original proof is the correct one. Is this something you really need in practice? Using it feels like admitting that we messed up earlier, but can recover anyways.

Eric Wieser (Nov 15 2021 at 13:51):

I don't know for sure; the context of this is the callers ofsigma_eq_of_reindex_cast in #10255, where I actually only need the version when the index type is fin n. It probably makes more sense to state things in terms of fin.cast in that case, but if I can rewrite cast to fin.cast I don't need to add the special case there.

Eric Wieser (Nov 15 2021 at 13:52):

This probably also relates to your tuple stuff in #4406 vs docs#fin.append, where your tuple.append didn't take a proof argument, but docs#fin.append does.

Reid Barton (Nov 15 2021 at 14:05):

I don't see anywhere in either of these examples that involves thinking about fin n = fin m rather than n = m

Eric Wieser (Nov 15 2021 at 14:13):

(congr_arg ι h) on line 457 of pi_tensor_product is the statement fin n = fin m. I guess in theory you can recover h : n = m from that via inference though

Reid Barton (Nov 15 2021 at 14:14):

oh I didn't read the whole name of the function

Reid Barton (Nov 15 2021 at 14:15):

Well anyways, you obviously don't need this early in the import hierarchy

Eric Wieser (Nov 15 2021 at 14:16):

I need it early if I want to replace fin.cast_eq_cast with fin.cast_eq_cast' and make it a simp lemma, but I don't have a particularly good reason to need to do that.

Eric Wieser (Nov 15 2021 at 14:19):

Anyway, PR'd with the short proof as #10330

Eric Rodriguez (Nov 15 2021 at 14:25):

I mean, I think the list proof suffices

Eric Rodriguez (Nov 15 2021 at 14:25):

(as in, you can use list.range_fin and do exactly the same proof)

Eric Wieser (Nov 15 2021 at 14:29):

That proof is probably ugly in the middle step:

lemma fin_injective : function.injective fin :=
λ m n h,
  (list.length_fin_range m).symm.trans $ eq.trans sorry (list.length_fin_range n)

Floris van Doorn (Nov 15 2021 at 14:40):

This lemma talks about equality of types, which is "evil".

If we add this to the library, it should come with a warning , in my opinion.

In your application, the usage of docs#equiv.cast is also evil. The non-evil way to do this is to use

import data.equiv.basic

def equiv.cast' {ι} (P : ι  Type*) {i j : ι} (h : i = j) : P i  P j :=
cast (congr_arg P h), cast (congr_arg P h.symm),
  λ x, by { cases h, refl }, λ x, by { cases h, refl }⟩

Floris van Doorn (Nov 15 2021 at 14:41):

If you use that everywhere (where P = fin, of course), you should never have to worry about equality of types, only equality of different indices.

Eric Rodriguez (Nov 15 2021 at 15:23):

However, I think there is a way to get the evilness working; propext means that subtype is injective. Currently on mobile but I'll write this up when I get home

Eric Wieser (Nov 15 2021 at 16:15):

Floris van Doorn said:

The non-evil way to do this is to use

import data.equiv.basic

def equiv.cast' {ι} (P : ι  Type*) {i j : ι} (h : i = j) : P i  P j :=
cast (congr_arg P h), cast (congr_arg P h.symm),
  λ x, by { cases h, refl }, λ x, by { cases h, refl }⟩

Isn's this precisely src#equiv.cast other than congr_arg P h.symm vs (congr_arg P h).symm? docs#equiv.cast_symm fixes that part of the term anyway when actually working with equiv.cast

Eric Rodriguez (Nov 15 2021 at 17:37):

I am carrying on with my evil project... I really hope this is provable:

import data.fin.basic

example {α} : function.injective (@subtype α) :=
begin
  intros p q h,
  let f := equiv.cast h,
  ext,
  refine λ hp, _, sorry⟩,
  have := cast_heq h x, hp⟩,
  --rw subtype.heq_iff_coe_eq at this,
  convert (cast h x, hp⟩).prop, sorry
  -- x = ↑(cast h ⟨x, hp⟩)
  -- this: cast h ⟨x, hp⟩ == ⟨x, hp⟩
end

does anyone know?

Reid Barton (Nov 15 2021 at 17:38):

function.injective (@subtype α) isn't provable, but if you consider subtype p together with its associated subtype.val then it becomes injective.

Gabriel Ebner (Nov 15 2021 at 17:39):

I'm pretty sure this is independent of Lean. IIRC there is a model of Lean where α ≃ β → α = β is a theorem. And @subtype α (eq a) ≃ @subtype α (eq b) even if a ≠ b.

Eric Rodriguez (Nov 15 2021 at 17:42):

i thought univalence was incompatible with lean?

Gabriel Ebner (Nov 15 2021 at 17:43):

Univalence is more, it's (α ≃ β) ≃ (α = β) (roughly).

Eric Rodriguez (Nov 15 2021 at 17:44):

I need to just sit down and read the HoTT book some day. that's wild

Johan Commelin (Nov 15 2021 at 17:49):

It suffices to read the first bit. Which I found very readable.

Floris van Doorn (Nov 15 2021 at 17:49):

Eric Wieser said:

Isn's this precisely src#equiv.cast other than congr_arg P h.symm vs (congr_arg P h).symm? docs#equiv.cast_symm fixes that part of the term anyway when actually working with equiv.cast

It is the non-evil special case of equiv.cast

Eric Wieser (Nov 15 2021 at 17:53):

Although it's still evil when P = id, right?

Floris van Doorn (Nov 15 2021 at 18:11):

Yes, because then the argument h is evil.

Eric Wieser (Nov 15 2021 at 18:33):

What makes equiv.cast (congr_arg P h) more evil than equiv.cast' P h?

Eric Wieser (Nov 15 2021 at 18:34):

Can unification retrieve h in the latter case and not the former?


Last updated: Dec 20 2023 at 11:08 UTC