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]
    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
      

Proof state:
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
split : e.suff = ys
eq :
  e.bound =
    (List.get ↑(suffixLevenshtein C xs ys) { val := 0, isLt := (_ : 0 < List.length ↑(suffixLevenshtein C xs ys)) },
      List.length ys)
x✝ : e.distances = suffixLevenshtein C xs e.suff
⊢ match
    match [], split 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:
exact eq