l3lab/ntp-mathlib huggingface dataset:
theorem mem_permutationsAux_of_perm :
    ∀ {ts is l : List α},
      l ~ is ++ ts → (∃ (is' : _) (_ : is' ~ is), l = is' ++ ts) ∨ l ∈ permutationsAux ts is := by
  show ∀ (ts is l : List α),
      l ~ is ++ ts → (∃ (is' : _) (_ : is' ~ is), l = is' ++ ts) ∨ l ∈ permutationsAux ts is
  refine' permutationsAux.rec (by simp) _
  intro t ts is IH1 IH2 l p
  rw [permutationsAux_cons, mem_foldr_permutationsAux2]
  rcases IH1 _ (p.trans perm_middle) with (⟨is', p', e⟩ | m)
  · clear p
    subst e
    rcases mem_split (p'.symm.subset (mem_cons_self _ _)) with ⟨l₁, l₂, e⟩
    subst is'
    have p := (perm_middle.symm.trans p').cons_inv
    

Proof state:
case inl.intro.intro.intro.intro
α : Type u_1
β : Type u_2
l l₁✝ l₂✝ : List α
a t : α
ts is : List α
IH1 :
  ∀ (l : List α), l ~ t :: is ++ ts → (∃ is', ∃ (_ : is' ~ t :: is), l = is' ++ ts) ∨ l ∈ permutationsAux ts (t :: is)
IH2 : ∀ (l : List α), l ~ [] ++ is → (∃ is', ∃ (_ : is' ~ []), l = is' ++ is) ∨ l ∈ permutationsAux is []
l₁ l₂ : List α
p' : l₁ ++ t :: l₂ ~ t :: is
p : l₁ ++ l₂ ~ is
⊢ (∃ is', ∃ (_ : is' ~ is), l₁ ++ t :: l₂ ++ ts = is' ++ t :: ts) ∨
    l₁ ++ t :: l₂ ++ ts ∈ permutationsAux ts (t :: is) ∨
      ∃ l₁_1 l₂_1, l₁_1 ++ l₂_1 ∈ permutations is ∧ l₂_1 ≠ [] ∧ l₁ ++ t :: l₂ ++ ts = l₁_1 ++ t :: l₂_1 ++ ts

Next tactic:
cases' l₂ with a l₂'
theorem mem_permutationsAux_of_perm :
    ∀ {ts is l : List α},
      l ~ is ++ ts → (∃ (is' : _) (_ : is' ~ is), l = is' ++ ts) ∨ l ∈ permutationsAux ts is := by
  show ∀ (ts is l : List α),
      l ~ is ++ ts → (∃ (is' : _) (_ : is' ~ is), l = is' ++ ts) ∨ l ∈ permutationsAux ts is
  refine' permutationsAux.rec (by simp) _
  intro t ts is IH1 IH2 l p
  rw [permutationsAux_cons, mem_foldr_permutationsAux2]
  rcases IH1 _ (p.trans perm_middle) with (⟨is', p', e⟩ | m)
  · clear p
    subst e
    rcases mem_split (p'.symm.subset (mem_cons_self _ _)) with ⟨l₁, l₂, e⟩
    subst is'
    have p := (perm_middle.symm.trans p').cons_inv
    cases' l₂ with a l₂'
    · 

Proof state:
case inl.intro.intro.intro.intro.nil
α : Type u_1
β : Type u_2
l l₁✝ l₂ : List α
a t : α
ts is : List α
IH1 :
  ∀ (l : List α), l ~ t :: is ++ ts → (∃ is', ∃ (_ : is' ~ t :: is), l = is' ++ ts) ∨ l ∈ permutationsAux ts (t :: is)
IH2 : ∀ (l : List α), l ~ [] ++ is → (∃ is', ∃ (_ : is' ~ []), l = is' ++ is) ∨ l ∈ permutationsAux is []
l₁ : List α
p' : l₁ ++ [t] ~ t :: is
p : l₁ ++ [] ~ is
⊢ (∃ is', ∃ (_ : is' ~ is), l₁ ++ [t] ++ ts = is' ++ t :: ts) ∨
    l₁ ++ [t] ++ ts ∈ permutationsAux ts (t :: is) ∨
      ∃ l₁_1 l₂, l₁_1 ++ l₂ ∈ permutations is ∧ l₂ ≠ [] ∧ l₁ ++ [t] ++ ts = l₁_1 ++ t :: l₂ ++ ts

Next tactic:
exact Or.inl ⟨l₁, by simpa using p⟩
theorem mem_permutationsAux_of_perm :
    ∀ {ts is l : List α},
      l ~ is ++ ts → (∃ (is' : _) (_ : is' ~ is), l = is' ++ ts) ∨ l ∈ permutationsAux ts is := by
  show ∀ (ts is l : List α),
      l ~ is ++ ts → (∃ (is' : _) (_ : is' ~ is), l = is' ++ ts) ∨ l ∈ permutationsAux ts is
  refine' permutationsAux.rec (by simp) _
  intro t ts is IH1 IH2 l p
  rw [permutationsAux_cons, mem_foldr_permutationsAux2]
  rcases IH1 _ (p.trans perm_middle) with (⟨is', p', e⟩ | m)
  · clear p
    subst e
    rcases mem_split (p'.symm.subset (mem_cons_self _ _)) with ⟨l₁, l₂, e⟩
    subst is'
    have p := (perm_middle.symm.trans p').cons_inv
    cases' l₂ with a l₂'
    · exact Or.inl ⟨l₁, by 

Proof state:
α : Type u_1
β : Type u_2
l l₁✝ l₂ : List α
a t : α
ts is : List α
IH1 :
  ∀ (l : List α), l ~ t :: is ++ ts → (∃ is', ∃ (_ : is' ~ t :: is), l = is' ++ ts) ∨ l ∈ permutationsAux ts (t :: is)
IH2 : ∀ (l : List α), l ~ [] ++ is → (∃ is', ∃ (_ : is' ~ []), l = is' ++ is) ∨ l ∈ permutationsAux is []
l₁ : List α
p' : l₁ ++ [t] ~ t :: is
p : l₁ ++ [] ~ is
⊢ ∃ (_ : l₁ ~ is), l₁ ++ [t] ++ ts = l₁ ++ t :: ts

Next tactic:
simpa using p
theorem mem_permutationsAux_of_perm :
    ∀ {ts is l : List α},
      l ~ is ++ ts → (∃ (is' : _) (_ : is' ~ is), l = is' ++ ts) ∨ l ∈ permutationsAux ts is := by
  show ∀ (ts is l : List α),
      l ~ is ++ ts → (∃ (is' : _) (_ : is' ~ is), l = is' ++ ts) ∨ l ∈ permutationsAux ts is
  refine' permutationsAux.rec (by simp) _
  intro t ts is IH1 IH2 l p
  rw [permutationsAux_cons, mem_foldr_permutationsAux2]
  rcases IH1 _ (p.trans perm_middle) with (⟨is', p', e⟩ | m)
  · clear p
    subst e
    rcases mem_split (p'.symm.subset (mem_cons_self _ _)) with ⟨l₁, l₂, e⟩
    subst is'
    have p := (perm_middle.symm.trans p').cons_inv
    cases' l₂ with a l₂'
    · exact Or.inl ⟨l₁, by simpa using p⟩
    · 

Proof state:
case inl.intro.intro.intro.intro.cons
α : Type u_1
β : Type u_2
l l₁✝ l₂ : List α
a✝ t : α
ts is : List α
IH1 :
  ∀ (l : List α), l ~ t :: is ++ ts → (∃ is', ∃ (_ : is' ~ t :: is), l = is' ++ ts) ∨ l ∈ permutationsAux ts (t :: is)
IH2 : ∀ (l : List α), l ~ [] ++ is → (∃ is', ∃ (_ : is' ~ []), l = is' ++ is) ∨ l ∈ permutationsAux is []
l₁ : List α
a : α
l₂' : List α
p' : l₁ ++ t :: a :: l₂' ~ t :: is
p : l₁ ++ a :: l₂' ~ is
⊢ (∃ is', ∃ (_ : is' ~ is), l₁ ++ t :: a :: l₂' ++ ts = is' ++ t :: ts) ∨
    l₁ ++ t :: a :: l₂' ++ ts ∈ permutationsAux ts (t :: is) ∨
      ∃ l₁_1 l₂, l₁_1 ++ l₂ ∈ permutations is ∧ l₂ ≠ [] ∧ l₁ ++ t :: a :: l₂' ++ ts = l₁_1 ++ t :: l₂ ++ ts

Next tactic:
exact Or.inr (Or.inr ⟨l₁, a :: l₂', mem_permutations_of_perm_lemma (IH2 _) p, by simp⟩)
theorem mem_permutationsAux_of_perm :
    ∀ {ts is l : List α},
      l ~ is ++ ts → (∃ (is' : _) (_ : is' ~ is), l = is' ++ ts) ∨ l ∈ permutationsAux ts is := by
  show ∀ (ts is l : List α),
      l ~ is ++ ts → (∃ (is' : _) (_ : is' ~ is), l = is' ++ ts) ∨ l ∈ permutationsAux ts is
  refine' permutationsAux.rec (by simp) _
  intro t ts is IH1 IH2 l p
  rw [permutationsAux_cons, mem_foldr_permutationsAux2]
  rcases IH1 _ (p.trans perm_middle) with (⟨is', p', e⟩ | m)
  · clear p
    subst e
    rcases mem_split (p'.symm.subset (mem_cons_self _ _)) with ⟨l₁, l₂, e⟩
    subst is'
    have p := (perm_middle.symm.trans p').cons_inv
    cases' l₂ with a l₂'
    · exact Or.inl ⟨l₁, by simpa using p⟩
    · exact Or.inr (Or.inr ⟨l₁, a :: l₂', mem_permutations_of_perm_lemma (IH2 _) p, by 

Proof state:
α : Type u_1
β : Type u_2
l l₁✝ l₂ : List α
a✝ t : α
ts is : List α
IH1 :
  ∀ (l : List α), l ~ t :: is ++ ts → (∃ is', ∃ (_ : is' ~ t :: is), l = is' ++ ts) ∨ l ∈ permutationsAux ts (t :: is)
IH2 : ∀ (l : List α), l ~ [] ++ is → (∃ is', ∃ (_ : is' ~ []), l = is' ++ is) ∨ l ∈ permutationsAux is []
l₁ : List α
a : α
l₂' : List α
p' : l₁ ++ t :: a :: l₂' ~ t :: is
p : l₁ ++ a :: l₂' ~ is
⊢ a :: l₂' ≠ [] ∧ l₁ ++ t :: a :: l₂' ++ ts = l₁ ++ t :: a :: l₂' ++ ts

Next tactic:
simp
theorem mem_permutationsAux_of_perm :
    ∀ {ts is l : List α},
      l ~ is ++ ts → (∃ (is' : _) (_ : is' ~ is), l = is' ++ ts) ∨ l ∈ permutationsAux ts is := by
  show ∀ (ts is l : List α),
      l ~ is ++ ts → (∃ (is' : _) (_ : is' ~ is), l = is' ++ ts) ∨ l ∈ permutationsAux ts is
  refine' permutationsAux.rec (by simp) _
  intro t ts is IH1 IH2 l p
  rw [permutationsAux_cons, mem_foldr_permutationsAux2]
  rcases IH1 _ (p.trans perm_middle) with (⟨is', p', e⟩ | m)
  · clear p
    subst e
    rcases mem_split (p'.symm.subset (mem_cons_self _ _)) with ⟨l₁, l₂, e⟩
    subst is'
    have p := (perm_middle.symm.trans p').cons_inv
    cases' l₂ with a l₂'
    · exact Or.inl ⟨l₁, by simpa using p⟩
    · exact Or.inr (Or.inr ⟨l₁, a :: l₂', mem_permutations_of_perm_lemma (IH2 _) p, by simp⟩)
  · 

Proof state:
case inr
α : Type u_1
β : Type u_2
l✝ l₁ l₂ : List α
a t : α
ts is : List α
IH1 :
  ∀ (l : List α), l ~ t :: is ++ ts → (∃ is', ∃ (_ : is' ~ t :: is), l = is' ++ ts) ∨ l ∈ permutationsAux ts (t :: is)
IH2 : ∀ (l : List α), l ~ [] ++ is → (∃ is', ∃ (_ : is' ~ []), l = is' ++ is) ∨ l ∈ permutationsAux is []
l : List α
p : l ~ is ++ t :: ts
m : l ∈ permutationsAux ts (t :: is)
⊢ (∃ is', ∃ (_ : is' ~ is), l = is' ++ t :: ts) ∨
    l ∈ permutationsAux ts (t :: is) ∨ ∃ l₁ l₂, l₁ ++ l₂ ∈ permutations is ∧ l₂ ≠ [] ∧ l = l₁ ++ t :: l₂ ++ ts

Next tactic:
exact Or.inr (Or.inl m)
private theorem DecEq_eq {α : Type*} [DecidableEq α] :
     instBEqList = @instBEq (List α) instDecidableEqList :=
  congr_arg BEq.mk <| by
    

Proof state:
α✝ : Type u_1
β : Type u_2
l l₁ l₂ : List α✝
a : α✝
α : Type u_3
inst✝ : DecidableEq α
⊢ List.beq = fun a b => decide (a = b)

Next tactic:
funext l₁ l₂
private theorem DecEq_eq {α : Type*} [DecidableEq α] :
     instBEqList = @instBEq (List α) instDecidableEqList :=
  congr_arg BEq.mk <| by
    funext l₁ l₂
    

Proof state:
case h.h
α✝ : Type u_1
β : Type u_2
l l₁✝ l₂✝ : List α✝
a : α✝
α : Type u_3
inst✝ : DecidableEq α
l₁ l₂ : List α
⊢ List.beq l₁ l₂ = decide (l₁ = l₂)

Next tactic:
show (l₁ == l₂) = _
private theorem DecEq_eq {α : Type*} [DecidableEq α] :
     instBEqList = @instBEq (List α) instDecidableEqList :=
  congr_arg BEq.mk <| by
    funext l₁ l₂
    show (l₁ == l₂) = _
    

Proof state:
case h.h
α✝ : Type u_1
β : Type u_2
l l₁✝ l₂✝ : List α✝
a : α✝
α : Type u_3
inst✝ : DecidableEq α
l₁ l₂ : List α
⊢ (l₁ == l₂) = decide (l₁ = l₂)

Next tactic:
rw [Bool.eq_iff_eq_true_iff, @beq_iff_eq _ (_), decide_eq_true_iff]
theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
    (permutations'Aux a l).bind (permutations'Aux b) ~
      (permutations'Aux b l).bind (permutations'Aux a) := by
  

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ : List α
a✝ a b : α
l : List α
⊢ List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)

Next tactic:
induction' l with c l ih
theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
    (permutations'Aux a l).bind (permutations'Aux b) ~
      (permutations'Aux b l).bind (permutations'Aux a) := by
  induction' l with c l ih
  · 

Proof state:
case nil
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a✝ a b : α
⊢ List.bind (permutations'Aux a []) (permutations'Aux b) ~ List.bind (permutations'Aux b []) (permutations'Aux a)

Next tactic:
simp [swap]
theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
    (permutations'Aux a l).bind (permutations'Aux b) ~
      (permutations'Aux b l).bind (permutations'Aux a) := by
  induction' l with c l ih
  · simp [swap]
  

Proof state:
case cons
α : Type u_1
β : Type u_2
l✝ l₁ l₂ : List α
a✝ a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
⊢ List.bind (permutations'Aux a (c :: l)) (permutations'Aux b) ~
    List.bind (permutations'Aux b (c :: l)) (permutations'Aux a)

Next tactic:
simp only [permutations'Aux, cons_bind, map_cons, map_map, cons_append]
theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
    (permutations'Aux a l).bind (permutations'Aux b) ~
      (permutations'Aux b l).bind (permutations'Aux a) := by
  induction' l with c l ih
  · simp [swap]
  simp only [permutations'Aux, cons_bind, map_cons, map_map, cons_append]
  

Proof state:
case cons
α : Type u_1
β : Type u_2
l✝ l₁ l₂ : List α
a✝ a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
⊢ (b :: a :: c :: l) ::
      (a :: b :: c :: l) ::
        (map (cons a ∘ cons c) (permutations'Aux b l) ++
          List.bind (map (cons c) (permutations'Aux a l)) (permutations'Aux b)) ~
    (a :: b :: c :: l) ::
      (b :: a :: c :: l) ::
        (map (cons b ∘ cons c) (permutations'Aux a l) ++
          List.bind (map (cons c) (permutations'Aux b l)) (permutations'Aux a))

Next tactic:
apply Perm.swap'
theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
    (permutations'Aux a l).bind (permutations'Aux b) ~
      (permutations'Aux b l).bind (permutations'Aux a) := by
  induction' l with c l ih
  · simp [swap]
  simp only [permutations'Aux, cons_bind, map_cons, map_map, cons_append]
  apply Perm.swap'
  

Proof state:
case cons.p
α : Type u_1
β : Type u_2
l✝ l₁ l₂ : List α
a✝ a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
⊢ map (cons a ∘ cons c) (permutations'Aux b l) ++ List.bind (map (cons c) (permutations'Aux a l)) (permutations'Aux b) ~
    map (cons b ∘ cons c) (permutations'Aux a l) ++ List.bind (map (cons c) (permutations'Aux b l)) (permutations'Aux a)

Next tactic:
have :
    ∀ a b,
      (map (cons c) (permutations'Aux a l)).bind (permutations'Aux b) ~
        map (cons b ∘ cons c) (permutations'Aux a l) ++
          map (cons c) ((permutations'Aux a l).bind (permutations'Aux b)) := by
    intros a' b'
    simp only [map_bind, permutations'Aux]
    show List.bind (permutations'Aux _ l) (fun a => ([b' :: c :: a] ++
      map (cons c) (permutations'Aux _ a))) ~ _
    refine' (bind_append_perm _ (fun x => [b' :: c :: x]) _).symm.trans _
    rw [← map_eq_bind, ← bind_map]
    exact Perm.refl _
theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
    (permutations'Aux a l).bind (permutations'Aux b) ~
      (permutations'Aux b l).bind (permutations'Aux a) := by
  induction' l with c l ih
  · simp [swap]
  simp only [permutations'Aux, cons_bind, map_cons, map_map, cons_append]
  apply Perm.swap'
  have :
    ∀ a b,
      (map (cons c) (permutations'Aux a l)).bind (permutations'Aux b) ~
        map (cons b ∘ cons c) (permutations'Aux a l) ++
          map (cons c) ((permutations'Aux a l).bind (permutations'Aux b)) := by
    

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ : List α
a✝ a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
⊢ ∀ (a b : α),
    List.bind (map (cons c) (permutations'Aux a l)) (permutations'Aux b) ~
      map (cons b ∘ cons c) (permutations'Aux a l) ++
        map (cons c) (List.bind (permutations'Aux a l) (permutations'Aux b))

Next tactic:
intros a' b'
theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
    (permutations'Aux a l).bind (permutations'Aux b) ~
      (permutations'Aux b l).bind (permutations'Aux a) := by
  induction' l with c l ih
  · simp [swap]
  simp only [permutations'Aux, cons_bind, map_cons, map_map, cons_append]
  apply Perm.swap'
  have :
    ∀ a b,
      (map (cons c) (permutations'Aux a l)).bind (permutations'Aux b) ~
        map (cons b ∘ cons c) (permutations'Aux a l) ++
          map (cons c) ((permutations'Aux a l).bind (permutations'Aux b)) := by
    intros a' b'
    

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ : List α
a✝ a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
a' b' : α
⊢ List.bind (map (cons c) (permutations'Aux a' l)) (permutations'Aux b') ~
    map (cons b' ∘ cons c) (permutations'Aux a' l) ++
      map (cons c) (List.bind (permutations'Aux a' l) (permutations'Aux b'))

Next tactic:
simp only [map_bind, permutations'Aux]
theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
    (permutations'Aux a l).bind (permutations'Aux b) ~
      (permutations'Aux b l).bind (permutations'Aux a) := by
  induction' l with c l ih
  · simp [swap]
  simp only [permutations'Aux, cons_bind, map_cons, map_map, cons_append]
  apply Perm.swap'
  have :
    ∀ a b,
      (map (cons c) (permutations'Aux a l)).bind (permutations'Aux b) ~
        map (cons b ∘ cons c) (permutations'Aux a l) ++
          map (cons c) ((permutations'Aux a l).bind (permutations'Aux b)) := by
    intros a' b'
    simp only [map_bind, permutations'Aux]
    

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ : List α
a✝ a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
a' b' : α
⊢ (List.bind (permutations'Aux a' l) fun a => (b' :: c :: a) :: map (cons c) (permutations'Aux b' a)) ~
    map (cons b' ∘ cons c) (permutations'Aux a' l) ++
      map (cons c) (List.bind (permutations'Aux a' l) (permutations'Aux b'))

Next tactic:
show List.bind (permutations'Aux _ l) (fun a => ([b' :: c :: a] ++
      map (cons c) (permutations'Aux _ a))) ~ _
theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
    (permutations'Aux a l).bind (permutations'Aux b) ~
      (permutations'Aux b l).bind (permutations'Aux a) := by
  induction' l with c l ih
  · simp [swap]
  simp only [permutations'Aux, cons_bind, map_cons, map_map, cons_append]
  apply Perm.swap'
  have :
    ∀ a b,
      (map (cons c) (permutations'Aux a l)).bind (permutations'Aux b) ~
        map (cons b ∘ cons c) (permutations'Aux a l) ++
          map (cons c) ((permutations'Aux a l).bind (permutations'Aux b)) := by
    intros a' b'
    simp only [map_bind, permutations'Aux]
    show List.bind (permutations'Aux _ l) (fun a => ([b' :: c :: a] ++
      map (cons c) (permutations'Aux _ a))) ~ _
    

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ : List α
a✝ a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
a' b' : α
⊢ (List.bind (permutations'Aux a' l) fun a => [b' :: c :: a] ++ map (cons c) (permutations'Aux b' a)) ~
    map (cons b' ∘ cons c) (permutations'Aux a' l) ++
      map (cons c) (List.bind (permutations'Aux a' l) (permutations'Aux b'))

Next tactic:
refine' (bind_append_perm _ (fun x => [b' :: c :: x]) _).symm.trans _
theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
    (permutations'Aux a l).bind (permutations'Aux b) ~
      (permutations'Aux b l).bind (permutations'Aux a) := by
  induction' l with c l ih
  · simp [swap]
  simp only [permutations'Aux, cons_bind, map_cons, map_map, cons_append]
  apply Perm.swap'
  have :
    ∀ a b,
      (map (cons c) (permutations'Aux a l)).bind (permutations'Aux b) ~
        map (cons b ∘ cons c) (permutations'Aux a l) ++
          map (cons c) ((permutations'Aux a l).bind (permutations'Aux b)) := by
    intros a' b'
    simp only [map_bind, permutations'Aux]
    show List.bind (permutations'Aux _ l) (fun a => ([b' :: c :: a] ++
      map (cons c) (permutations'Aux _ a))) ~ _
    refine' (bind_append_perm _ (fun x => [b' :: c :: x]) _).symm.trans _
    

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ : List α
a✝ a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
a' b' : α
⊢ ((List.bind (permutations'Aux a' l) fun x => [b' :: c :: x]) ++
      List.bind (permutations'Aux a' l) fun a => map (cons c) (permutations'Aux b' a)) ~
    map (cons b' ∘ cons c) (permutations'Aux a' l) ++
      map (cons c) (List.bind (permutations'Aux a' l) (permutations'Aux b'))

Next tactic:
rw [← map_eq_bind, ← bind_map]
theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
    (permutations'Aux a l).bind (permutations'Aux b) ~
      (permutations'Aux b l).bind (permutations'Aux a) := by
  induction' l with c l ih
  · simp [swap]
  simp only [permutations'Aux, cons_bind, map_cons, map_map, cons_append]
  apply Perm.swap'
  have :
    ∀ a b,
      (map (cons c) (permutations'Aux a l)).bind (permutations'Aux b) ~
        map (cons b ∘ cons c) (permutations'Aux a l) ++
          map (cons c) ((permutations'Aux a l).bind (permutations'Aux b)) := by
    intros a' b'
    simp only [map_bind, permutations'Aux]
    show List.bind (permutations'Aux _ l) (fun a => ([b' :: c :: a] ++
      map (cons c) (permutations'Aux _ a))) ~ _
    refine' (bind_append_perm _ (fun x => [b' :: c :: x]) _).symm.trans _
    rw [← map_eq_bind, ← bind_map]
    

Proof state:
α : Type u_1
β : Type u_2
l✝ l₁ l₂ : List α
a✝ a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
a' b' : α
⊢ map (fun x => b' :: c :: x) (permutations'Aux a' l) ++
      map (cons c) (List.bind (permutations'Aux a' l) fun a => permutations'Aux b' a) ~
    map (cons b' ∘ cons c) (permutations'Aux a' l) ++
      map (cons c) (List.bind (permutations'Aux a' l) (permutations'Aux b'))

Next tactic:
exact Perm.refl _
theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
    (permutations'Aux a l).bind (permutations'Aux b) ~
      (permutations'Aux b l).bind (permutations'Aux a) := by
  induction' l with c l ih
  · simp [swap]
  simp only [permutations'Aux, cons_bind, map_cons, map_map, cons_append]
  apply Perm.swap'
  have :
    ∀ a b,
      (map (cons c) (permutations'Aux a l)).bind (permutations'Aux b) ~
        map (cons b ∘ cons c) (permutations'Aux a l) ++
          map (cons c) ((permutations'Aux a l).bind (permutations'Aux b)) := by
    intros a' b'
    simp only [map_bind, permutations'Aux]
    show List.bind (permutations'Aux _ l) (fun a => ([b' :: c :: a] ++
      map (cons c) (permutations'Aux _ a))) ~ _
    refine' (bind_append_perm _ (fun x => [b' :: c :: x]) _).symm.trans _
    rw [← map_eq_bind, ← bind_map]
    exact Perm.refl _
  

Proof state:
case cons.p
α : Type u_1
β : Type u_2
l✝ l₁ l₂ : List α
a✝ a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
this :
  ∀ (a b : α),
    List.bind (map (cons c) (permutations'Aux a l)) (permutations'Aux b) ~
      map (cons b ∘ cons c) (permutations'Aux a l) ++
        map (cons c) (List.bind (permutations'Aux a l) (permutations'Aux b))
⊢ map (cons a ∘ cons c) (permutations'Aux b l) ++ List.bind (map (cons c) (permutations'Aux a l)) (permutations'Aux b) ~
    map (cons b ∘ cons c) (permutations'Aux a l) ++ List.bind (map (cons c) (permutations'Aux b l)) (permutations'Aux a)

Next tactic:
refine' (((this _ _).append_left _).trans _).trans ((this _ _).append_left _).symm
theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
    (permutations'Aux a l).bind (permutations'Aux b) ~
      (permutations'Aux b l).bind (permutations'Aux a) := by
  induction' l with c l ih
  · simp [swap]
  simp only [permutations'Aux, cons_bind, map_cons, map_map, cons_append]
  apply Perm.swap'
  have :
    ∀ a b,
      (map (cons c) (permutations'Aux a l)).bind (permutations'Aux b) ~
        map (cons b ∘ cons c) (permutations'Aux a l) ++
          map (cons c) ((permutations'Aux a l).bind (permutations'Aux b)) := by
    intros a' b'
    simp only [map_bind, permutations'Aux]
    show List.bind (permutations'Aux _ l) (fun a => ([b' :: c :: a] ++
      map (cons c) (permutations'Aux _ a))) ~ _
    refine' (bind_append_perm _ (fun x => [b' :: c :: x]) _).symm.trans _
    rw [← map_eq_bind, ← bind_map]
    exact Perm.refl _
  refine' (((this _ _).append_left _).trans _).trans ((this _ _).append_left _).symm
  

Proof state:
case cons.p
α : Type u_1
β : Type u_2
l✝ l₁ l₂ : List α
a✝ a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
this :
  ∀ (a b : α),
    List.bind (map (cons c) (permutations'Aux a l)) (permutations'Aux b) ~
      map (cons b ∘ cons c) (permutations'Aux a l) ++
        map (cons c) (List.bind (permutations'Aux a l) (permutations'Aux b))
⊢ map (cons a ∘ cons c) (permutations'Aux b l) ++
      (map (cons b ∘ cons c) (permutations'Aux a l) ++
        map (cons c) (List.bind (permutations'Aux a l) (permutations'Aux b))) ~
    map (cons b ∘ cons c) (permutations'Aux a l) ++
      (map (cons a ∘ cons c) (permutations'Aux b l) ++
        map (cons c) (List.bind (permutations'Aux b l) (permutations'Aux a)))

Next tactic:
rw [← append_assoc, ← append_assoc]