Zulip Chat Archive

Stream: general

Topic: Problems with coercion and function subsets


Tomas Skrivan (Oct 21 2020 at 23:54):

Let's define a set of all constant functions

def is_constant (f : ) : Prop :=  n m, f n = f m

def const_fun := { f :    // is_constant f}

I want to work with f : const_fun as with a function, thus I define coercion to fun

@[reducible, inline] instance const_fun.has_coe_to_fun : has_coe_to_fun const_fun := has_coe_to_fun.mk _ subtype.val

Just a simple lemma testing that the coercion works

lemma lemma1 (f : const_fun) (n : ) : f n = f.val n :=
begin
  simp,
end

Now, here is the bizarre thing, if you import import data.set then the proof by simp does not work anymore.

In the proof, simp changes goal from ⇑f n = f.val n to ⇑f n = ↑f n. What is going on here?

Bryan Gin-ge Chen (Oct 21 2020 at 23:59):

You can add set_option trace.simplify.rewrite true before your code to see what simp is doing in each case.

Bryan Gin-ge Chen (Oct 22 2020 at 00:00):

In this case, without the import, simp is using eq_self_iff_true, and with the import simp uses subtype.val_eq_coe.

Bryan Gin-ge Chen (Oct 22 2020 at 00:00):

You could write simp only [eq_self_iff_true] to get the proof to work with the import.

Tomas Skrivan (Oct 22 2020 at 01:09):

I'm too lazy to write simp only [eq_self_iff_true], I just want simp to work as expected.

The solution I have found is to do:

@[reducible, inline] def get_coe {α : Sort*} {p : α  Prop} (x : subtype p) : α := x
@[reducible, inline] instance const_fun.has_coe_to_fun : has_coe_to_fun const_fun := has_coe_to_fun.mk _ get_coe

For some reason I have to define the auxiliary function get_coe, because simply writing

@[reducible, inline] instance const_fun.has_coe_to_fun : has_coe_to_fun const_fun := has_coe_to_fun.mk (λ _, ) (λ f, f)

I get an error

error: failed to synthesize type class instance for
f : const_fun
 has_lift_t const_fun (  )

Reid Barton (Oct 22 2020 at 01:12):

This is all rather unidiomatic

Reid Barton (Oct 22 2020 at 01:18):

You can prove lemma1 by refl, and I wouldn't recommend putting @[reducible, inline] on everything (I don't even know what @[inline] does). If you want simp to do specific things, then add simp lemmas.

Tomas Skrivan (Oct 22 2020 at 01:23):

The main problem is when I state some lemma, like ⇑f (⇑f n) = ⇑f 0 and then I'm proving another lemma by using simp. I can end up with a goal F ↑f (⇑f n) = F ⇑f 0 for some F : ℕ → ℕ . Now I'm in a trouble, if ⇑f and ↑f are not equal by definition then rewrite tactic has problem using my original lemma ⇑f (⇑f n) = ⇑f 0.

Johan Commelin (Oct 22 2020 at 03:24):

It looks to me like they are defeq, they are just not syneq.

Floris van Doorn (Oct 22 2020 at 21:28):

mathlib has a simp lemma that subtype.val is reduced to the coercion. That's why you get the ↑f. Add your own simp lemma stating that ↑f reduces to ⇑f, and you should be good. (You might have to state the lemma explicitly with docs#coe_subtype)


Last updated: Dec 20 2023 at 11:08 UTC