Zulip Chat Archive

Stream: mathlib4

Topic: difficulty porting List.perm_inv_core


Scott Morrison (Sep 19 2022 at 01:59):

I need to port List.perm_inv_core from mathlib3 to mathlib4.

To do so, I have copied and pasted (and slightly cleaned up) the beginning of mathport's suggestion, adding

@[elabAsElim]
theorem perm_induction_on {P : List α  List α  Prop} {l₁ l₂ : List α} (p : l₁ ~ l₂) (h₁ : P [] [])
    (h₂ :  x l₁ l₂, l₁ ~ l₂  P l₁ l₂  P (x :: l₁) (x :: l₂))
    (h₃ :  x y l₁ l₂, l₁ ~ l₂  P l₁ l₂  P (y :: x :: l₁) (x :: y :: l₂))
    (h₄ :  l₁ l₂ l₃, l₁ ~ l₂  l₂ ~ l₃  P l₁ l₂  P l₂ l₃  P l₁ l₃) : P l₁ l₂ :=
  have P_refl :  l, P l l := fun l => List.recOn l h₁ fun x xs ih => h₂ x xs xs (Perm.refl xs) ih
  Perm.recOn p h₁ h₂ (fun x y l => h₃ x y l l (Perm.refl l) (P_refl l)) @h₄

theorem perm_inv_core {a : α} {l₁ l₂ r₁ r₂ : List α} : l₁ ++ a :: r₁ ~ l₂ ++ a :: r₂  l₁ ++ r₁ ~ l₂ ++ r₂ := by
  generalize e₁ : l₁ ++ a :: r₁ = s₁
  generalize e₂ : l₂ ++ a :: r₂ = s₂
  intro p
  revert l₁ l₂ r₁ r₂ e₁ e₂
  refine' perm_induction_on p _ (fun x t₁ t₂ p IH => _) (fun x y t₁ t₂ p IH => _) (fun t₁ t₂ t₃ p₁ p₂ IH₁ IH₂ => _)
  · sorry
  · sorry
  · sorry
  · sorry

to the bottom of Mathlib/Data/List/Perm.lean in the master branch of mathlib4.

However, the refine' tactic is producing a result that I haven't been able to understand.

The goals become:

case refine'_1
α: Type u_1
a: α
s₁s₂: List α
p: s₁ ~ s₂
l₁l₂r₁r₂: List α
 l₁ ++ a :: r₁ = s₁  l₂ ++ a :: r₂ = s₂  l₁ ++ r₁ ~ l₂ ++ r₂
case refine'_2
α: Type u_1
a: α
s₁s₂: List α
p: s₁ ~ s₂
l₁l₂r₁r₂: List α
 α 
   (t₁ t₂ : List α),
    t₁ ~ t₂ 
      (l₁ ++ a :: r₁ = s₁  l₂ ++ a :: r₂ = s₂  l₁ ++ r₁ ~ l₂ ++ r₂) 
        l₁ ++ a :: r₁ = s₁  l₂ ++ a :: r₂ = s₂  l₁ ++ r₁ ~ l₂ ++ r₂
case refine'_3
α: Type u_1
a: α
s₁s₂: List α
p: s₁ ~ s₂
l₁l₂r₁r₂: List α
 α 
  α 
     (t₁ t₂ : List α),
      t₁ ~ t₂ 
        (l₁ ++ a :: r₁ = s₁  l₂ ++ a :: r₂ = s₂  l₁ ++ r₁ ~ l₂ ++ r₂) 
          l₁ ++ a :: r₁ = s₁  l₂ ++ a :: r₂ = s₂  l₁ ++ r₁ ~ l₂ ++ r₂
case refine'_4
α: Type u_1
a: α
s₁s₂: List α
p: s₁ ~ s₂
l₁l₂r₁r₂: List α
  (t₁ t₂ t₃ : List α),
  t₁ ~ t₂ 
    t₂ ~ t₃ 
      (l₁ ++ a :: r₁ = s₁  l₂ ++ a :: r₂ = s₂  l₁ ++ r₁ ~ l₂ ++ r₂) 
        (l₁ ++ a :: r₁ = s₁  l₂ ++ a :: r₂ = s₂  l₁ ++ r₁ ~ l₂ ++ r₂) 
          l₁ ++ a :: r₁ = s₁  l₂ ++ a :: r₂ = s₂  l₁ ++ r₁ ~ l₂ ++ r₂

whereas in mathlib3 at the corresponding point they were

4 goals
α: Type uu
a: α
s₁s₂: list α
p: s₁ ~ s₂
  {l₁ l₂ r₁ r₂ : list α}, l₁ ++ a :: r₁ = nil  l₂ ++ a :: r₂ = nil  l₁ ++ r₁ ~ l₂ ++ r₂
α: Type uu
a: α
s₁s₂: list α
p: s₁ ~ s₂
x: α
t₁: list α
t₂: list α
p: t₁ ~ t₂
IH:  {l₁ l₂ r₁ r₂ : list α}, l₁ ++ a :: r₁ = t₁  l₂ ++ a :: r₂ = t₂  l₁ ++ r₁ ~ l₂ ++ r₂
  {l₁ l₂ r₁ r₂ : list α}, l₁ ++ a :: r₁ = x :: t₁  l₂ ++ a :: r₂ = x :: t₂  l₁ ++ r₁ ~ l₂ ++ r₂
α: Type uu
a: α
s₁s₂: list α
p: s₁ ~ s₂
x: α
y: α
t₁: list α
t₂: list α
p: t₁ ~ t₂
IH:  {l₁ l₂ r₁ r₂ : list α}, l₁ ++ a :: r₁ = t₁  l₂ ++ a :: r₂ = t₂  l₁ ++ r₁ ~ l₂ ++ r₂
  {l₁ l₂ r₁ r₂ : list α}, l₁ ++ a :: r₁ = y :: x :: t₁  l₂ ++ a :: r₂ = x :: y :: t₂  l₁ ++ r₁ ~ l₂ ++ r₂
α: Type uu
a: α
s₁s₂: list α
p: s₁ ~ s₂
t₁: list α
t₂: list α
t₃: list α
p₁: t₁ ~ t₂
p₂: t₂ ~ t₃
IH₁:  {l₁ l₂ r₁ r₂ : list α}, l₁ ++ a :: r₁ = t₁  l₂ ++ a :: r₂ = t₂  l₁ ++ r₁ ~ l₂ ++ r₂
IH₂:  {l₁ l₂ r₁ r₂ : list α}, l₁ ++ a :: r₁ = t₂  l₂ ++ a :: r₂ = t₃  l₁ ++ r₁ ~ l₂ ++ r₂
  {l₁ l₂ r₁ r₂ : list α}, l₁ ++ a :: r₁ = t₁  l₂ ++ a :: r₂ = t₃  l₁ ++ r₁ ~ l₂ ++ r₂

Can anyone assist me in working out how to successfully apply perm_induction_on here?

Mario Carneiro (Sep 19 2022 at 04:20):

It looks like implicit lambdas triggered just before the perm_induction_on application, meaning that it's actually doing refine' fun {l1 l2 r1 r2} => perm_induction_on p _ (fun x t₁ t₂ p IH => _) (fun x y t₁ t₂ p IH => _) (fun t₁ t₂ t₃ p₁ p₂ IH₁ IH₂ => _) which is not what you want

Mario Carneiro (Sep 19 2022 at 04:28):

You can disable implicit lambdas by using @ before perm_induction_on, although that will also make the arguments to perm_induction_on explicit; possibly@(perm_induction_on ..) does what you want (EDIT: confirmed)

Scott Morrison (Sep 19 2022 at 04:37):

Thanks. That solves the tombstone issue. I now see that there are two separate problems: note that the goal in the first branch is now

case refine'_1
α: Type u_1
a: α
s₁s₂: List α
p: s₁ ~ s₂
l₁l₂r₁r₂: List α
e₁: l₁ ++ a :: r₁ = s₁
e₂: l₂ ++ a :: r₂ = s₂
 l₁ ++ r₁ ~ l₂ ++ r₂

whereas in the mathlib3 version we have

e₁: l₁ ++ a :: r₁ = nil
e₂: l₂ ++ a :: r₂ = nil

(which is what we need to proceed!)

Mario Carneiro (Sep 19 2022 at 04:42):

I don't understand that goal at all, it looks like you didn't do anything

Mario Carneiro (Sep 19 2022 at 04:42):

what's the actual term you used?

Mario Carneiro (Sep 19 2022 at 04:42):

also show_term might help

Mario Carneiro (Sep 19 2022 at 04:45):

maybe the motive didn't abstract over s1 and s2 correctly? elabAsElim is relatively untested for mathlib problems so there could be an elaboration bug

Scott Morrison (Sep 19 2022 at 04:51):

show_term refine' @(perm_induction_on p _ (fun x t₁ t₂ p IH => _) (fun x y t₁ t₂ p IH => _) (fun t₁ t₂ t₃ p₁ p₂ IH₁ IH₂ => _)) prints:

𝔗𝔯𝔶 𝔱𝔥𝔦𝔰: refine
  @perm_induction_on α
    (fun x x =>  {l₁ l₂ r₁ r₂ : List α}, l₁ ++ a :: r₁ = s₁  l₂ ++ a :: r₂ = s₂  l₁ ++ r₁ ~ l₂ ++ r₂) s₁ s₂ p
    (fun {l₁} => @?_ l₁) (fun x t₁ t₂ p IH => @?_ x t₁ t₂ p IH) (fun x y t₁ t₂ p IH => @?_ x y t₁ t₂ p IH)
    fun t₁ t₂ t₃ p₁ p₂ IH₁ IH₂ => @?_ t₁ t₂ t₃ p₁ p₂ IH₁ IH₂

Scott Morrison (Sep 19 2022 at 04:57):

This is pretty trivial to separate from mathlib, so I'll create a Lean4 issue, as it seems it's an elaboration bug with elabAsElim.


Last updated: Dec 20 2023 at 11:08 UTC