Zulip Chat Archive
Stream: mathlib4
Topic: logic.equiv.basic mathlib4#631
Scott Morrison (Nov 22 2022 at 22:50):
We're very close on logic.equiv.basic.
Scott Morrison (Nov 22 2022 at 22:50):
The remaining problem is the simpNF linter is unhappy with lemmas like:
theorem sumCompl_apply_symm_of_pos (p : α → Prop) [DecidablePred p] (a : α) (h : p a) :
(sumCompl p).symm a = Sum.inl ⟨a, h⟩ :=
dif_pos h
Scott Morrison (Nov 22 2022 at 22:50):
It doesn't explain why, and just says you'll have to debug it yourself.
Scott Morrison (Nov 22 2022 at 22:50):
The current PR has just removed the @[simp]
on this lemma (and three others like it), but I'm as yet unconvinced.
Scott Morrison (Nov 22 2022 at 22:51):
As long as simp
can prove p a
itself, it seems this is a perfectly reasonable simp
lemma.
Scott Morrison (Nov 22 2022 at 22:51):
Or am I forgetting that something about simp
has changed in Lean 4, and it is less aggressive about solving side-conditions?
Mario Carneiro (Nov 22 2022 at 22:52):
can you make a MWE version (no mathlib)?
Scott Morrison (Nov 22 2022 at 22:59):
import Std.Tactic.Lint
protected def Sum.elim {α β γ : Sort _} (f : α → γ) (g : β → γ) : Sum α β → γ :=
fun x => Sum.casesOn x f g
structure Equiv (α : Sort _) (β : Sort _) where
toFun : α → β
invFun : β → α
infixl:25 " ≃ " => Equiv
namespace Equiv
instance : CoeFun (α ≃ β) fun _ => α → β := ⟨toFun⟩
protected def symm (e : α ≃ β) : β ≃ α := ⟨e.invFun, e.toFun⟩
def sumCompl {α : Type _} (p : α → Prop) [DecidablePred p] :
Sum { a // p a } { a // ¬p a } ≃ α where
toFun := Sum.elim Subtype.val Subtype.val
invFun a := if h : p a then Sum.inl ⟨a, h⟩ else Sum.inr ⟨a, h⟩
@[simp]
theorem sumCompl_apply_symm_of_pos (p : α → Prop) [DecidablePred p] (a : α) (h : p a) :
(sumCompl p).symm a = Sum.inl ⟨a, h⟩ :=
dif_pos h
#lint
/- The `simpNF` linter reports:
SOME SIMP LEMMAS ARE NOT IN SIMP-NORMAL FORM.
see note [simp-normal form] for tips how to debug this.
https://leanprover-community.github.io/mathlib_docs/notes.html#simp-normal%20form -/
#check @sumCompl_apply_symm_of_pos /- Left-hand side does not simplify.
You need to debug this yourself using `set_option trace.Meta.Tactic.simp.rewrite true` -/
Kevin Buzzard (Nov 22 2022 at 23:13):
example (p : α → Prop) [DecidablePred p] (a : α) (h : p a) :
(sumCompl p).symm a = Sum.inl ⟨a, h⟩ := by simp -- fails :-(
I can't even make set_option trace.Meta.Tactic.simp.rewrite true
do anything. Where am I supposed to be writing this and/or looking at the output?
Mario Carneiro (Nov 22 2022 at 23:17):
The error message is saying that simp
does not rewrite with the simp lemma
Mario Carneiro (Nov 22 2022 at 23:18):
so set_option trace.Meta.Tactic.simp.rewrite true
will predictably be empty
Mario Carneiro (Nov 22 2022 at 23:23):
fixed in 68581a4
Scott Morrison (Nov 22 2022 at 23:23):
Oh, it is saying that it can't simplify the LHS, even using the simp lemma itself? I assumed it was about not simplifying with other simp lemmas.
Mario Carneiro (Nov 22 2022 at 23:24):
not simplifying with other simp lemmas is the good case
Mario Carneiro (Nov 22 2022 at 23:25):
simp lemma LHSs should not simplify when using everything else in the simp set, and they should simplify when using the simp lemma itself
Scott Morrison (Nov 22 2022 at 23:26):
Could we change the error message for when they do not simplify when using the simp lemma itself?
Scott Morrison (Nov 22 2022 at 23:27):
To be explicit that this is the test that is failing? I missed that in this case.
Scott Morrison (Nov 22 2022 at 23:32):
Weird,
@[simp] theorem coe_fn_mk (f : α → β) (g l r) : (Equiv.mk f g l r : α → β) = f :=
rfl
was omitted in Logic.Equiv.Defs
...
Kevin Buzzard (Nov 22 2022 at 23:35):
Where is this simp lemma supposed to find h by the way?
Mario Carneiro (Nov 22 2022 at 23:37):
it's a conditional rewrite rule, it would normally be proved by recursive application of simp, possibly including hypotheses passed to the original invocation
Mario Carneiro (Nov 22 2022 at 23:37):
the bug here was that it failed to detect that this was a conditional rewrite rule
Scott Morrison (Nov 22 2022 at 23:38):
Okay, Logic.Equiv.Basic
now compiles and lints locally.
Scott Morrison (Nov 22 2022 at 23:38):
Review would be great.
Scott Morrison (Nov 23 2022 at 02:03):
Hmm, we're not there yet. My fixes for duplicate Coe instances in Logic.Equiv.Defs
has broken things in other places.
Scott Morrison (Nov 23 2022 at 02:05):
in Order.Monotone
,
@[simp]
theorem monotone_toDual_comp_iff : Monotone (toDual ∘ f) ↔ Antitone f :=
Iff.rfl
is now failing with
type mismatch
Iff.rfl
has type
Monotone (FunLike.coe toDual ∘ f) ↔ Monotone (FunLike.coe toDual ∘ f) : Prop
but is expected to have type
Monotone (FunLike.coe toDual ∘ f) ↔ Antitone f : Prop
I neither understand why the FunLike.coe
is printing here, nor why Iff.rfl
doesn't work... :-(
Mario Carneiro (Nov 23 2022 at 02:07):
I think the FunLike.coe
printing might be because it is an under-application? Can you make a MWE? (I think functions with the right arity and implicitness for FunLike.coe
and toDual
should suffice)
Mario Carneiro (Nov 23 2022 at 02:09):
for the iff.rfl proof it might help to look at set_option trace.Meta.isDefEq true
Mario Carneiro (Nov 23 2022 at 02:35):
@Scott Morrison I took a look at this issue, and the reason the iff.rfl proof fails is because Monotone
has inferred the original order on beta, not the dual one
Scott Morrison (Nov 23 2022 at 02:42):
:racecar:, yes
Scott Morrison (Nov 23 2022 at 02:42):
Curiously before I took away the duplicate Coe instance for Equiv, this proof was working.
Scott Morrison (Nov 23 2022 at 02:43):
Perhaps because the duplicate one was not a coercion to a dependently typed function.
Scott Morrison (Nov 23 2022 at 02:43):
And this made it easier for Lean to get the type right?
Scott Morrison (Nov 23 2022 at 02:45):
I can add type ascriptions, but it feels like a work-around rather than a solution.
Scott Morrison (Nov 23 2022 at 02:48):
Could we have a higher priority CoeFun
for FunLike
s indexed by a constant type family?
Mario Carneiro (Nov 23 2022 at 03:07):
MWE:
class MyFunLike (F : Sort _) (β : outParam <| Nat → Sort _) where
coe : F → ∀ a, β a
inductive Secret
def Wrapper := Secret
inductive Bla | z
instance : MyFunLike Bla (fun _ => Wrapper) := sorry
instance (priority := 100) {F β} [MyFunLike F β] :
CoeFun F fun _ => ∀ a : Nat, β a where coe := MyFunLike.coe
#check Bla.z 0 -- MyFunLike.coe Bla.z 0 : (fun x => Wrapper) 0
set_option trace.Meta.isDefEq true in
#check Bla.z ∘ id -- MyFunLike.coe Bla.z ∘ id : ℤ → Secret
Scott Morrison (Nov 23 2022 at 03:11):
So you think this is something that should be fixed in core?
Mario Carneiro (Nov 23 2022 at 03:12):
yes, there is at least one core bug here
Scott Morrison (Nov 23 2022 at 13:19):
In mathlib4#631, I have just worked around this issue for now (and left a note pointing to this thread).
Scott Morrison (Nov 23 2022 at 13:20):
Shall I post your MWE as a Lean 4 issue, or is it still in your court?
Scott Morrison (Nov 23 2022 at 13:20):
Separately, mathlib4#631 now has a green tick, so if someone would like to have a look and/or merge that would be great.
Kevin Buzzard (Nov 23 2022 at 14:40):
(looking now)
Scott Morrison (Nov 23 2022 at 16:41):
@Kevin Buzzard, @Eric Rodriguez, @Ruben Van de Velde, thanks for all the review comments. Would you mind, where possible, just making the changes? It's twice as much work to have conversations about things.
Kevin Buzzard (Nov 23 2022 at 16:42):
I'll make my changes, all of which are trivial.
Scott Morrison (Nov 23 2022 at 16:43):
Thanks.
Ruben Van de Velde (Nov 23 2022 at 16:51):
I'll deal with min now, unless you already started, @Scott Morrison
Scott Morrison (Nov 23 2022 at 17:10):
I think I got them.
Scott Morrison (Nov 23 2022 at 17:11):
Here's the #mwe extracted from this branch:
notation:arg "⟦" a "⟧" => Quotient.mk _ a
namespace Function
def LeftInverse (g : β → α) (f : α → β) : Prop := ∀ x, g (f x) = x
def RightInverse (g : β → α) (f : α → β) : Prop := LeftInverse f g
theorem hfunext {α α': Sort u} {β : α → Sort v} {β' : α' → Sort v} {f : ∀a, β a} {f' : ∀a, β' a}
(hα : α = α') (h : ∀a a', HEq a a' → HEq (f a) (f' a')) : HEq f f' := by
subst hα
have : ∀a, HEq (f a) (f' a) := λ a => h a a (HEq.refl a)
have : β = β' := by funext a
exact type_eq_of_heq (this a)
subst this
apply heq_of_eq
funext a
exact eq_of_heq (this a)
end Function
namespace Subtype
variable {α β γ : Sort _} {p q : α → Prop}
protected theorem ext : ∀ {a1 a2 : { x // p x }}, (a1 : α) = (a2 : α) → a1 = a2
| ⟨_, _⟩, ⟨_, _⟩, rfl => rfl
theorem ext_val {a1 a2 : { x // p x }} : a1.1 = a2.1 → a1 = a2 :=
Subtype.ext
end Subtype
open Function
structure Equiv (α : Sort _) (β : Sort _) where
toFun : α → β
invFun : β → α
left_inv : LeftInverse invFun toFun
right_inv : RightInverse invFun toFun
infixl:25 " ≃ " => Equiv
def subtypeQuotientEquivQuotientSubtype (p₁ : α → Prop) [s₁ : Setoid α] [s₂ : Setoid (Subtype p₁)]
(p₂ : Quotient s₁ → Prop) (hp₂ : ∀ a, p₁ a ↔ p₂ ⟦a⟧)
(h : ∀ x y : Subtype p₁, @Setoid.r _ s₂ x y ↔ (x : α) ≈ y) :
{ x // p₂ x } ≃ Quotient s₂ where
toFun a :=
Quotient.hrecOn a.1 (fun a h => ⟦⟨a, (hp₂ _).2 h⟩⟧)
(fun a b hab => hfunext (by rw [Quotient.sound hab]) fun h₁ h₂ _ =>
heq_of_eq (Quotient.sound ((h _ _).2 hab)))
a.2
invFun a :=
Quotient.liftOn a (fun a => (⟨⟦a.1⟧, (hp₂ _).1 a.2⟩ : { x // p₂ x })) fun a b hab =>
Subtype.ext_val (Quotient.sound ((h _ _).1 hab))
-- This fails (but worked in Lean 3), but the next line using `rcases` succeeds:
left_inv := fun ⟨a, ha⟩ => Quotient.inductionOn a (fun b hb => rfl) ha
-- Needs `import Std.Tactic.RCases`:
-- left_inv t := by rcases t with ⟨a, ha⟩; exact Quotient.inductionOn a (fun b hb => rfl) ha
right_inv a := Quotient.inductionOn a fun ⟨a, ha⟩ => rfl
Scott Morrison (Nov 23 2022 at 17:11):
(Sorry, it's not super minimal...)
Scott Morrison (Nov 23 2022 at 17:12):
Unless someone has an idea I will post an issue on the Lean 4 repository. If anyone wants to further minimise first, that would be great.
Scott Morrison (Nov 23 2022 at 17:12):
For now I'll just put a link to this message at the regression in mathlib4#631, but let's not otherwise wait.
Kyle Miller (Nov 23 2022 at 17:46):
I think in that MWE that left_inv t
is meant to be left_inv
Kyle Miller (Nov 23 2022 at 17:47):
I tried using intro
with a pattern match, and it creates two goals. I used Quotient.sound
to handle one of them, but then it lead to there being an error on a random other line...
def subtypeQuotientEquivQuotientSubtype (p₁ : α → Prop) [s₁ : Setoid α] [s₂ : Setoid (Subtype p₁)]
(p₂ : Quotient s₁ → Prop) (hp₂ : ∀ a, p₁ a ↔ p₂ ⟦a⟧)
(h : ∀ x y : Subtype p₁, @Setoid.r _ s₂ x y ↔ (x : α) ≈ y) :
{ x // p₂ x } ≃ Quotient s₂ where
toFun a :=
Quotient.hrecOn a.1 (fun a h => ⟦⟨a, (hp₂ _).2 h⟩⟧)
(fun a b hab => hfunext (by rw [Quotient.sound hab]) fun h₁ h₂ _ => -- why is there now an error on `rw`??
heq_of_eq (Quotient.sound ((h _ _).2 hab)))
a.2
invFun a :=
Quotient.liftOn a (fun a => (⟨⟦a.1⟧, (hp₂ _).1 a.2⟩ : { x // p₂ x })) fun a b hab =>
Subtype.ext_val (Quotient.sound ((h _ _).1 hab))
left_inv := --fun ⟨a, ha⟩ => Quotient.inductionOn a (fun b hb => rfl) ha
-- Workaround:
by
intro ⟨a, ha⟩
· simp [Quotient.sound hab]
exact Quotient.inductionOn a (fun b hb => rfl) ha
right_inv a := Quotient.inductionOn a fun ⟨a, ha⟩ => rfl
Gabriel Ebner (Nov 23 2022 at 19:09):
I think this is a just a typical elaboration order / metavariables not instantiated yet kind of issue. If you insert a by exact
after left_inv
it works.
Last updated: Dec 20 2023 at 11:08 UTC