Module docstring
{"# Join of a list of lists
This file proves basic properties of List.flatten, which concatenates a list of lists. It is
defined in Init.Data.List.Basic.
"}
{"# Join of a list of lists
This file proves basic properties of List.flatten, which concatenates a list of lists. It is
defined in Init.Data.List.Basic.
"}
List.Sublist.flatten
      theorem
     {l₁ l₂ : List (List α)} (h : l₁ <+ l₂) : l₁.flatten <+ l₂.flatten
        @[gcongr]
protected theorem Sublist.flatten {l₁ l₂ : List (List α)} (h : l₁ <+ l₂) :
    l₁.flatten <+ l₂.flatten := by
  induction h with
  | slnil => simp
  | cons _ _ ih =>
    rw [flatten_cons]
    exact ih.trans (sublist_append_right _ _)
  | cons₂ _ _ ih => simpa
        List.Sublist.flatMap
      theorem
     {l₁ l₂ : List α} (h : l₁ <+ l₂) (f : α → List β) : l₁.flatMap f <+ l₂.flatMap f
        @[gcongr]
protected theorem Sublist.flatMap {l₁ l₂ : List α} (h : l₁ <+ l₂) (f : α → List β) :
    l₁.flatMap f <+ l₂.flatMap f :=
  (h.map f).flatten
        List.drop_take_succ_eq_cons_getElem
      theorem
     (L : List α) (i : Nat) (h : i < L.length) : (L.take (i + 1)).drop i = [L[i]]
        /-- Taking only the first `i+1` elements in a list, and then dropping the first `i` ones, one is
left with a list of length `1` made of the `i`-th element of the original list. -/
theorem drop_take_succ_eq_cons_getElem (L : List α) (i : Nat) (h : i < L.length) :
    (L.take (i + 1)).drop i = [L[i]] := by
  induction L generalizing i with
  | nil => exact (Nat.not_succ_le_zero i h).elim
  | cons head tail ih =>
    rcases i with _ | i
    · simp
    · simpa using ih _ (by simpa using h)
        List.append_flatten_map_append
      theorem
     (L : List (List α)) (x : List α) : x ++ (L.map (· ++ x)).flatten = (L.map (x ++ ·)).flatten ++ x
        /-- We can rebracket `x ++ (l₁ ++ x) ++ (l₂ ++ x) ++ ... ++ (lₙ ++ x)` to
`(x ++ l₁) ++ (x ++ l₂) ++ ... ++ (x ++ lₙ) ++ x` where `L = [l₁, l₂, ..., lₙ]`. -/
theorem append_flatten_map_append (L : List (List α)) (x : List α) :
    x ++ (L.map (· ++ x)).flatten = (L.map (x ++ ·)).flatten ++ x := by
  induction L with
  | nil => rw [map_nil, flatten, append_nil, map_nil, flatten, nil_append]
  | cons _ _ ih =>
    rw [map_cons, flatten, map_cons, flatten, append_assoc, ih, append_assoc, append_assoc]