-- Frap/Exercises/IndProp.lean

namespace Hidden

inductive List (α : Type u) where
  | nil  : List α
  | cons : α → List α → List α

namespace List

def reverse {α : Type u} (as : List α) : List α :=
  match as with
  | nil        => nil
  | cons a as' => reverse as' ++ cons a nil

-- Repository definitions used:
content: ...

-- Repository lemmas used:
content: theorem List.getElem_append_left{α : Type u_1} {l₁ l₂ : List α} {i : Nat} (hn : i < l₁.length) :\n(l₁ ++ l₂)[i] = l₁[i]

-- Local definitions used:
content: inductive List (α : Type u) where
  | nil  : List α
  | cons : α → List α → List α

content: def reverse {α : Type u} (as : List α) : List α :=
  match as with
  | nil        => nil
  | cons a as' => reverse as' ++ cons a nil

-- Local lemmas used:
content: theorem nil_append (as : List α) : nil ++ as = as

content: theorem cons_append (a : α) (as bs : List α)
        : (cons a as) ++ bs = cons a (as ++ bs)

content: theorem append_nil (as : List α) : as ++ nil = as

content: theorem append_assoc (as bs cs : List α)
        : (as ++ bs) ++ cs = as ++ (bs ++ cs)

-- Target theorem and proof:
theorem reverse_append {α : Type u} (as bs : List α)
    : reverse (as ++ bs) = reverse bs ++ reverse as
:= by
  induction as with
  | nil =>
      rw [nil_append, reverse, append_nil]
  | cons a as' ih =>
      rw [cons_append, reverse, reverse, ih, append_assoc]