Theorem: List.bidirectionalRec_cons_append
File: Mathlib/Data/List/Basic.lean

tactic: conv_lhs => unfold bidirectionalRec
state_before: ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
motive : List α → Sort u_2
nil : motive []
singleton : (a : α) → motive [a]
cons_append : (a : α) → (l : List α) → (b : α) → motive l → motive (a :: (l ++ [b]))
a : α
l : List α
b : α
⊢ bidirectionalRec nil singleton cons_append (a :: (l ++ [b])) =
    cons_append a l b (bidirectionalRec nil singleton cons_append l)
state_after: ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
motive : List α → Sort u_2
nil : motive []
singleton : (a : α) → motive [a]
cons_append : (a : α) → (l : List α) → (b : α) → motive l → motive (a :: (l ++ [b]))
a : α
l : List α
b : α
⊢ (match a :: (l ++ [b]) with
    | [] => nil
    | [a] => singleton a
    | a :: b :: l =>
      let l' := (b :: l).dropLast;
      let b' := (b :: l).getLast ⋯;
      cast ⋯ (cons_append a l' b' (bidirectionalRec nil singleton cons_append l'))) =
    cons_append a l b (bidirectionalRec nil singleton cons_append l)

tactic: cases l with
| nil => rfl
| cons x xs =>
simp only [List.cons_append]
dsimp only [← List.cons_append]
suffices ∀ (ys init : List α) (hinit : init = ys) (last : α) (hlast : last = b),
    (cons_append a init last
      (bidirectionalRec nil singleton cons_append init)) =
    cast (congr_arg motive <| by simp [hinit, hlast])
      (cons_append a ys b (bidirectionalRec nil singleton cons_append ys)) by
  rw [this (x :: xs) _ (by rw [dropLast_append_cons, dropLast_single, append_nil]) _ (by simp)]
  simp
rintro ys init rfl last rfl
rfl
state_before: ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
motive : List α → Sort u_2
nil : motive []
singleton : (a : α) → motive [a]
cons_append : (a : α) → (l : List α) → (b : α) → motive l → motive (a :: (l ++ [b]))
a : α
l : List α
b : α
⊢ (match a :: (l ++ [b]) with
    | [] => nil
    | [a] => singleton a
    | a :: b :: l =>
      let l' := (b :: l).dropLast;
      let b' := (b :: l).getLast ⋯;
      cast ⋯ (cons_append a l' b' (bidirectionalRec nil singleton cons_append l'))) =
    cons_append a l b (bidirectionalRec nil singleton cons_append l)
state_after: no goals

tactic: rfl
state_before: case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
motive : List α → Sort u_2
nil : motive []
singleton : (a : α) → motive [a]
cons_append : (a : α) → (l : List α) → (b : α) → motive l → motive (a :: (l ++ [b]))
a b : α
⊢ (match a :: ([] ++ [b]) with
    | [] => nil
    | [a] => singleton a
    | a :: b :: l =>
      let l' := (b :: l).dropLast;
      let b' := (b :: l).getLast ⋯;
      cast ⋯ (cons_append a l' b' (bidirectionalRec nil singleton cons_append l'))) =
    cons_append a [] b (bidirectionalRec nil singleton cons_append [])
state_after: no goals

tactic: simp only [List.cons_append]
state_before: case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
motive : List α → Sort u_2
nil : motive []
singleton : (a : α) → motive [a]
cons_append : (a : α) → (l : List α) → (b : α) → motive l → motive (a :: (l ++ [b]))
a b x : α
xs : List α
⊢ (match a :: (x :: xs ++ [b]) with
    | [] => nil
    | [a] => singleton a
    | a :: b :: l =>
      let l' := (b :: l).dropLast;
      let b' := (b :: l).getLast ⋯;
      cast ⋯ (cons_append a l' b' (bidirectionalRec nil singleton cons_append l'))) =
    cons_append a (x :: xs) b (bidirectionalRec nil singleton cons_append (x :: xs))
state_after: case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
motive : List α → Sort u_2
nil : motive []
singleton : (a : α) → motive [a]
cons_append : (a : α) → (l : List α) → (b : α) → motive l → motive (a :: (l ++ [b]))
a b x : α
xs : List α
⊢ cast ⋯
      (cons_append a (x :: (xs ++ [b])).dropLast ((x :: (xs ++ [b])).getLast ⋯)
        (bidirectionalRec nil singleton cons_append (x :: (xs ++ [b])).dropLast)) =
    cons_append a (x :: xs) b (bidirectionalRec nil singleton cons_append (x :: xs))

tactic: dsimp only [← List.cons_append]
state_before: case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
motive : List α → Sort u_2
nil : motive []
singleton : (a : α) → motive [a]
cons_append : (a : α) → (l : List α) → (b : α) → motive l → motive (a :: (l ++ [b]))
a b x : α
xs : List α
⊢ cast ⋯
      (cons_append a (x :: (xs ++ [b])).dropLast ((x :: (xs ++ [b])).getLast ⋯)
        (bidirectionalRec nil singleton cons_append (x :: (xs ++ [b])).dropLast)) =
    cons_append a (x :: xs) b (bidirectionalRec nil singleton cons_append (x :: xs))
state_after: case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
motive : List α → Sort u_2
nil : motive []
singleton : (a : α) → motive [a]
cons_append : (a : α) → (l : List α) → (b : α) → motive l → motive (a :: (l ++ [b]))
a b x : α
xs : List α
⊢ cast ⋯
      (cons_append a (x :: xs ++ [b]).dropLast ((x :: xs ++ [b]).getLast ⋯)
        (bidirectionalRec nil singleton cons_append (x :: xs ++ [b]).dropLast)) =
    cons_append a (x :: xs) b (bidirectionalRec nil singleton cons_append (x :: xs))

tactic: suffices ∀ (ys init : List α) (hinit : init = ys) (last : α) (hlast : last = b),
    (cons_append a init last
      (bidirectionalRec nil singleton cons_append init)) =
    cast (congr_arg motive <| by simp [hinit, hlast])
      (cons_append a ys b (bidirectionalRec nil singleton cons_append ys)) by
  rw [this (x :: xs) _ (by rw [dropLast_append_cons, dropLast_single, append_nil]) _ (by simp)]
  simp
state_before: case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
motive : List α → Sort u_2
nil : motive []
singleton : (a : α) → motive [a]
cons_append : (a : α) → (l : List α) → (b : α) → motive l → motive (a :: (l ++ [b]))
a b x : α
xs : List α
⊢ cast ⋯
      (cons_append a (x :: xs ++ [b]).dropLast ((x :: xs ++ [b]).getLast ⋯)
        (bidirectionalRec nil singleton cons_append (x :: xs ++ [b]).dropLast)) =
    cons_append a (x :: xs) b (bidirectionalRec nil singleton cons_append (x :: xs))
state_after: case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
motive : List α → Sort u_2
nil : motive []
singleton : (a : α) → motive [a]
cons_append : (a : α) → (l : List α) → (b : α) → motive l → motive (a :: (l ++ [b]))
a b x : α
xs : List α
⊢ ∀ (ys init : List α) (hinit : init = ys) (last : α) (hlast : last = b),
    cons_append a init last (bidirectionalRec nil singleton cons_append init) =
      cast ⋯ (cons_append a ys b (bidirectionalRec nil singleton cons_append ys))

tactic: rintro ys init rfl last rfl
state_before: case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
motive : List α → Sort u_2
nil : motive []
singleton : (a : α) → motive [a]
cons_append : (a : α) → (l : List α) → (b : α) → motive l → motive (a :: (l ++ [b]))
a b x : α
xs : List α
⊢ ∀ (ys init : List α) (hinit : init = ys) (last : α) (hlast : last = b),
    cons_append a init last (bidirectionalRec nil singleton cons_append init) =
      cast ⋯ (cons_append a ys b (bidirectionalRec nil singleton cons_append ys))
state_after: case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
motive : List α → Sort u_2
nil : motive []
singleton : (a : α) → motive [a]
cons_append : (a : α) → (l : List α) → (b : α) → motive l → motive (a :: (l ++ [b]))
a x : α
xs init : List α
last : α
⊢ cons_append a init last (bidirectionalRec nil singleton cons_append init) =
    cast ⋯ (cons_append a init last (bidirectionalRec nil singleton cons_append init))

tactic: rfl
state_before: case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
motive : List α → Sort u_2
nil : motive []
singleton : (a : α) → motive [a]
cons_append : (a : α) → (l : List α) → (b : α) → motive l → motive (a :: (l ++ [b]))
a x : α
xs init : List α
last : α
⊢ cons_append a init last (bidirectionalRec nil singleton cons_append init) =
    cast ⋯ (cons_append a init last (bidirectionalRec nil singleton cons_append init))
state_after: no goals

tactic: simp [hinit, hlast]
state_before: ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
motive : List α → Sort u_2
nil : motive []
singleton : (a : α) → motive [a]
cons_append : (a : α) → (l : List α) → (b : α) → motive l → motive (a :: (l ++ [b]))
a b x : α
xs ys init : List α
hinit : init = ys
last : α
hlast : last = b
⊢ a :: (ys ++ [b]) = a :: (init ++ [last])
state_after: no goals

tactic: rw [this (x :: xs) _ (by rw [dropLast_append_cons, dropLast_single, append_nil]) _ (by simp)]
state_before: ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
motive : List α → Sort u_2
nil : motive []
singleton : (a : α) → motive [a]
cons_append : (a : α) → (l : List α) → (b : α) → motive l → motive (a :: (l ++ [b]))
a b x : α
xs : List α
this :
  ∀ (ys init : List α) (hinit : init = ys) (last : α) (hlast : last = b),
    cons_append a init last (bidirectionalRec nil singleton cons_append init) =
      cast ⋯ (cons_append a ys b (bidirectionalRec nil singleton cons_append ys))
⊢ cast ⋯
      (cons_append a (x :: xs ++ [b]).dropLast ((x :: xs ++ [b]).getLast ⋯)
        (bidirectionalRec nil singleton cons_append (x :: xs ++ [b]).dropLast)) =
    cons_append a (x :: xs) b (bidirectionalRec nil singleton cons_append (x :: xs))
state_after: ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
motive : List α → Sort u_2
nil : motive []
singleton : (a : α) → motive [a]
cons_append : (a : α) → (l : List α) → (b : α) → motive l → motive (a :: (l ++ [b]))
a b x : α
xs : List α
this :
  ∀ (ys init : List α) (hinit : init = ys) (last : α) (hlast : last = b),
    cons_append a init last (bidirectionalRec nil singleton cons_append init) =
      cast ⋯ (cons_append a ys b (bidirectionalRec nil singleton cons_append ys))
⊢ cast ⋯ (cast ⋯ (cons_append a (x :: xs) b (bidirectionalRec nil singleton cons_append (x :: xs)))) =
    cons_append a (x :: xs) b (bidirectionalRec nil singleton cons_append (x :: xs))

tactic: simp
state_before: ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
motive : List α → Sort u_2
nil : motive []
singleton : (a : α) → motive [a]
cons_append : (a : α) → (l : List α) → (b : α) → motive l → motive (a :: (l ++ [b]))
a b x : α
xs : List α
this :
  ∀ (ys init : List α) (hinit : init = ys) (last : α) (hlast : last = b),
    cons_append a init last (bidirectionalRec nil singleton cons_append init) =
      cast ⋯ (cons_append a ys b (bidirectionalRec nil singleton cons_append ys))
⊢ cast ⋯ (cast ⋯ (cons_append a (x :: xs) b (bidirectionalRec nil singleton cons_append (x :: xs)))) =
    cons_append a (x :: xs) b (bidirectionalRec nil singleton cons_append (x :: xs))
state_after: no goals

tactic: rw [dropLast_append_cons, dropLast_single, append_nil]
state_before: ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
motive : List α → Sort u_2
nil : motive []
singleton : (a : α) → motive [a]
cons_append : (a : α) → (l : List α) → (b : α) → motive l → motive (a :: (l ++ [b]))
a b x : α
xs : List α
this :
  ∀ (ys init : List α) (hinit : init = ys) (last : α) (hlast : last = b),
    cons_append a init last (bidirectionalRec nil singleton cons_append init) =
      cast ⋯ (cons_append a ys b (bidirectionalRec nil singleton cons_append ys))
⊢ (x :: xs ++ [b]).dropLast = x :: xs
state_after: no goals

tactic: simp
state_before: ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
motive : List α → Sort u_2
nil : motive []
singleton : (a : α) → motive [a]
cons_append : (a : α) → (l : List α) → (b : α) → motive l → motive (a :: (l ++ [b]))
a b x : α
xs : List α
this :
  ∀ (ys init : List α) (hinit : init = ys) (last : α) (hlast : last = b),
    cons_append a init last (bidirectionalRec nil singleton cons_append init) =
      cast ⋯ (cons_append a ys b (bidirectionalRec nil singleton cons_append ys))
⊢ (x :: xs ++ [b]).getLast ⋯ = b
state_after: no goals