instance estimator' :
    Estimator (Thunk.mk fun _ => (levenshtein C xs ys, ys.length))
      (LevenshteinEstimator' C xs ys) where
  bound_le e := match e.pre_rev, e.split, e.bound_eq with
  | [], split, eq => by
    simp only [List.reverse_nil, List.nil_append] at split
    rw [e.distances_eq] at eq
    simp only [List.getElem_eq_get] at eq
    rw [split] at eq
    exact eq.le
  | y :: t, split, eq => by
    rw [e.distances_eq] at eq
    simp only at eq
    dsimp [EstimatorData.bound]
    rw [eq]
    simp only [← split]
    constructor
    · simp only [List.minimum_of_length_pos_le_iff]
      exact suffixLevenshtein_minimum_le_levenshtein_append _ _ _
    · exact List.length_le_of_sublist (List.sublist_append_right _ _)
  improve_spec e := by
    dsimp [EstimatorData.improve]
    

Proof state:
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
⊢ match
    match e.pre_rev, (_ : List.reverse e.pre_rev ++ e.suff = ys) with
    | [], x => none
    | y :: ys_1, split =>
      some
        { pre_rev := ys_1, suff := y :: e.suff, split := (_ : List.reverse ys_1 ++ ([y] ++ e.suff) = ys),
          distances := Levenshtein.impl C xs y e.distances,
          distances_eq := (_ : Levenshtein.impl C xs y e.distances = suffixLevenshtein C xs (y :: e.suff)),
          bound :=
            match ys_1, (_ : List.reverse ys_1 ++ ([y] ++ e.suff) = ys) with
            | [], split =>
              (List.get ↑(Levenshtein.impl C xs y e.distances)
                  { val := 0, isLt := (_ : 0 < List.length ↑(Levenshtein.impl C xs y e.distances)) },
                List.length ys)
            | x, split =>
              (List.minimum_of_length_pos (_ : 0 < List.length ↑(Levenshtein.impl C xs y e.distances)),
                Nat.succ (List.length e.suff)),
          bound_eq :=
            (_ :
              (match ys_1, (_ : List.reverse ys_1 ++ ([y] ++ e.suff) = ys) with
                | [], split => ((↑(Levenshtein.impl C xs y e.distances))[0], List.length ys)
                | x, split =>
                  (List.minimum_of_length_pos (_ : 0 < List.length ↑(Levenshtein.impl C xs y e.distances)),
                    List.length (y :: e.suff))) =
                match ys_1, (_ : List.reverse ys_1 ++ ([y] ++ e.suff) = ys) with
                | [], split => ((↑(Levenshtein.impl C xs y e.distances))[0], List.length ys)
                | x, split =>
                  (List.minimum_of_length_pos (_ : 0 < List.length ↑(Levenshtein.impl C xs y e.distances)),
                    List.length (y :: e.suff))) } with
  | none =>
    EstimatorData.bound { fn := fun x => (levenshtein C xs ys, List.length ys) } e =
      Thunk.get { fn := fun x => (levenshtein C xs ys, List.length ys) }
  | some e' =>
    EstimatorData.bound { fn := fun x => (levenshtein C xs ys, List.length ys) } e <
      EstimatorData.bound { fn := fun x => (levenshtein C xs ys, List.length ys) } e'

Next tactic:
match e.pre_rev, e.split, e.bound_eq, e.distances_eq with
    | [], split, eq, _ =>
      simp only [List.reverse_nil, List.nil_append] at split
      rw [e.distances_eq] at eq
      simp only [List.getElem_eq_get] at eq
      rw [split] at eq
      exact eq
    | [y], split, b_eq, d_eq =>
      simp only [EstimatorData.bound, Prod.lt_iff, List.reverse_nil, List.nil_append]
      right
      have b_eq : e.bound = (List.minimum_of_length_pos _, List.length e.suff) := by
        simpa using b_eq
      rw [b_eq]
      constructor
      · refine (?_ : _ ≤ _).trans (List.minimum_of_length_pos_le_getElem _)
        simp only [List.minimum_of_length_pos_le_iff, List.coe_minimum_of_length_pos, d_eq]
        apply le_suffixLevenshtein_cons_minimum
      · simp [← split]
    | y₁ :: y₂ :: t, split, b_eq, d_eq =>
      simp only [EstimatorData.bound, Prod.lt_iff]
      right
      have b_eq : e.bound = (List.minimum_of_length_pos _, List.length e.suff) := by
        simpa using b_eq
      rw [b_eq]
      constructor
      · simp only [d_eq, List.minimum_of_length_pos_le_iff, List.coe_minimum_of_length_pos]
        apply le_suffixLevenshtein_cons_minimum
      · exact Nat.lt.base _