l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem splitOnP_cons (x : α) (xs : List α) :
    (x :: xs).splitOnP p =
      if p x then [] :: xs.splitOnP p else (xs.splitOnP p).modifyHead (cons x) := by
  rw [splitOnP, splitOnP.go]; 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs✝ ys : List α
ls : List (List α)
f : List α → List α
x : α
xs : List α
⊢ (if p x = true then reverse [] :: splitOnP.go p xs [] else splitOnP.go p xs [x]) =
    if p x = true then [] :: splitOnP p xs else modifyHead (cons x) (splitOnP p xs)

Next tactic:
split <;> [rfl; simp [splitOnP.go_acc]]
@[simp]
theorem splitOnP_cons (x : α) (xs : List α) :
    (x :: xs).splitOnP p =
      if p x then [] :: xs.splitOnP p else (xs.splitOnP p).modifyHead (cons x) := by
  rw [splitOnP, splitOnP.go]; 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs✝ ys : List α
ls : List (List α)
f : List α → List α
x : α
xs : List α
⊢ (if p x = true then reverse [] :: splitOnP.go p xs [] else splitOnP.go p xs [x]) =
    if p x = true then [] :: splitOnP p xs else modifyHead (cons x) (splitOnP p xs)

Next tactic:
split
@[simp]
theorem splitOnP_cons (x : α) (xs : List α) :
    (x :: xs).splitOnP p =
      if p x then [] :: xs.splitOnP p else (xs.splitOnP p).modifyHead (cons x) := by
  rw [splitOnP, splitOnP.go]; split <;> [

Proof state:
case inl
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs✝ ys : List α
ls : List (List α)
f : List α → List α
x : α
xs : List α
h✝ : p x = true
⊢ reverse [] :: splitOnP.go p xs [] = [] :: splitOnP p xs

Next tactic:
rfl
@[simp]
theorem splitOnP_cons (x : α) (xs : List α) :
    (x :: xs).splitOnP p =
      if p x then [] :: xs.splitOnP p else (xs.splitOnP p).modifyHead (cons x) := by
  rw [splitOnP, splitOnP.go]; split <;> [rfl; 

Proof state:
case inr
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs✝ ys : List α
ls : List (List α)
f : List α → List α
x : α
xs : List α
h✝ : ¬p x = true
⊢ splitOnP.go p xs [x] = modifyHead (cons x) (splitOnP p xs)

Next tactic:
simp [splitOnP.go_acc]
/-- The original list `L` can be recovered by joining the lists produced by `splitOnP p L`,
interspersed with the elements `L.filter p`. -/
theorem splitOnP_spec (as : List α) :
    join (zipWith (· ++ ·) (splitOnP p as) (((as.filter p).map fun x => [x]) ++ [[]])) = as := by
  induction as with
  | nil => rfl
  | cons a as' ih =>
    rw [splitOnP_cons, filter]
    by_cases h : p a
    · rw [if_pos h, h, map, cons_append, zipWith, nil_append, join, cons_append, cons_inj]
      exact ih
    · rw [if_neg h, eq_false_of_ne_true h, join_zipWith (splitOnP_ne_nil _ _)
        (append_ne_nil_of_ne_nil_right _ [[]] (cons_ne_nil [] [])), cons_inj]
      exact ih
where
  join_zipWith {xs ys : List (List α)} {a : α} (hxs : xs ≠ []) (hys : ys ≠ []) :
      join (zipWith (fun x x_1 ↦ x ++ x_1) (modifyHead (cons a) xs) ys) =
        a :: join (zipWith (fun x x_1 ↦ x ++ x_1) xs ys) := by
    

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs✝ ys✝ : List α
ls : List (List α)
f : List α → List α
as : List α
xs ys : List (List α)
a : α
hxs : xs ≠ []
hys : ys ≠ []
⊢ join (zipWith (fun x x_1 => x ++ x_1) (modifyHead (cons a) xs) ys) = a :: join (zipWith (fun x x_1 => x ++ x_1) xs ys)

Next tactic:
cases xs with | nil => contradiction | cons =>
      cases ys with | nil => contradiction | cons => rfl
/-- The original list `L` can be recovered by joining the lists produced by `splitOnP p L`,
interspersed with the elements `L.filter p`. -/
theorem splitOnP_spec (as : List α) :
    join (zipWith (· ++ ·) (splitOnP p as) (((as.filter p).map fun x => [x]) ++ [[]])) = as := by
  induction as with
  | nil => rfl
  | cons a as' ih =>
    rw [splitOnP_cons, filter]
    by_cases h : p a
    · rw [if_pos h, h, map, cons_append, zipWith, nil_append, join, cons_append, cons_inj]
      exact ih
    · rw [if_neg h, eq_false_of_ne_true h, join_zipWith (splitOnP_ne_nil _ _)
        (append_ne_nil_of_ne_nil_right _ [[]] (cons_ne_nil [] [])), cons_inj]
      exact ih
where
  join_zipWith {xs ys : List (List α)} {a : α} (hxs : xs ≠ []) (hys : ys ≠ []) :
      join (zipWith (fun x x_1 ↦ x ++ x_1) (modifyHead (cons a) xs) ys) =
        a :: join (zipWith (fun x x_1 ↦ x ++ x_1) xs ys) := by
    cases xs with 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys✝ : List α
ls : List (List α)
f : List α → List α
as : List α
ys : List (List α)
a : α
hys : ys ≠ []
hxs : [] ≠ []
⊢ join (zipWith (fun x x_1 => x ++ x_1) (modifyHead (cons a) []) ys) = a :: join (zipWith (fun x x_1 => x ++ x_1) [] ys)

Next tactic:
| nil => contradiction
/-- The original list `L` can be recovered by joining the lists produced by `splitOnP p L`,
interspersed with the elements `L.filter p`. -/
theorem splitOnP_spec (as : List α) :
    join (zipWith (· ++ ·) (splitOnP p as) (((as.filter p).map fun x => [x]) ++ [[]])) = as := by
  induction as with
  | nil => rfl
  | cons a as' ih =>
    rw [splitOnP_cons, filter]
    by_cases h : p a
    · rw [if_pos h, h, map, cons_append, zipWith, nil_append, join, cons_append, cons_inj]
      exact ih
    · rw [if_neg h, eq_false_of_ne_true h, join_zipWith (splitOnP_ne_nil _ _)
        (append_ne_nil_of_ne_nil_right _ [[]] (cons_ne_nil [] [])), cons_inj]
      exact ih
where
  join_zipWith {xs ys : List (List α)} {a : α} (hxs : xs ≠ []) (hys : ys ≠ []) :
      join (zipWith (fun x x_1 ↦ x ++ x_1) (modifyHead (cons a) xs) ys) =
        a :: join (zipWith (fun x x_1 ↦ x ++ x_1) xs ys) := by
    cases xs with | nil => 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys✝ : List α
ls : List (List α)
f : List α → List α
as : List α
ys : List (List α)
a : α
hys : ys ≠ []
hxs : [] ≠ []
⊢ join (zipWith (fun x x_1 => x ++ x_1) (modifyHead (cons a) []) ys) = a :: join (zipWith (fun x x_1 => x ++ x_1) [] ys)

Next tactic:
contradiction
/-- The original list `L` can be recovered by joining the lists produced by `splitOnP p L`,
interspersed with the elements `L.filter p`. -/
theorem splitOnP_spec (as : List α) :
    join (zipWith (· ++ ·) (splitOnP p as) (((as.filter p).map fun x => [x]) ++ [[]])) = as := by
  induction as with
  | nil => rfl
  | cons a as' ih =>
    rw [splitOnP_cons, filter]
    by_cases h : p a
    · rw [if_pos h, h, map, cons_append, zipWith, nil_append, join, cons_append, cons_inj]
      exact ih
    · rw [if_neg h, eq_false_of_ne_true h, join_zipWith (splitOnP_ne_nil _ _)
        (append_ne_nil_of_ne_nil_right _ [[]] (cons_ne_nil [] [])), cons_inj]
      exact ih
where
  join_zipWith {xs ys : List (List α)} {a : α} (hxs : xs ≠ []) (hys : ys ≠ []) :
      join (zipWith (fun x x_1 ↦ x ++ x_1) (modifyHead (cons a) xs) ys) =
        a :: join (zipWith (fun x x_1 ↦ x ++ x_1) xs ys) := by
    cases xs with | nil => contradiction 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys✝ : List α
ls : List (List α)
f : List α → List α
as : List α
ys : List (List α)
a : α
hys : ys ≠ []
head✝ : List α
tail✝ : List (List α)
hxs : head✝ :: tail✝ ≠ []
⊢ join (zipWith (fun x x_1 => x ++ x_1) (modifyHead (cons a) (head✝ :: tail✝)) ys) =
    a :: join (zipWith (fun x x_1 => x ++ x_1) (head✝ :: tail✝) ys)

Next tactic:
| cons =>
      cases ys with | nil => contradiction | cons => rfl
/-- The original list `L` can be recovered by joining the lists produced by `splitOnP p L`,
interspersed with the elements `L.filter p`. -/
theorem splitOnP_spec (as : List α) :
    join (zipWith (· ++ ·) (splitOnP p as) (((as.filter p).map fun x => [x]) ++ [[]])) = as := by
  induction as with
  | nil => rfl
  | cons a as' ih =>
    rw [splitOnP_cons, filter]
    by_cases h : p a
    · rw [if_pos h, h, map, cons_append, zipWith, nil_append, join, cons_append, cons_inj]
      exact ih
    · rw [if_neg h, eq_false_of_ne_true h, join_zipWith (splitOnP_ne_nil _ _)
        (append_ne_nil_of_ne_nil_right _ [[]] (cons_ne_nil [] [])), cons_inj]
      exact ih
where
  join_zipWith {xs ys : List (List α)} {a : α} (hxs : xs ≠ []) (hys : ys ≠ []) :
      join (zipWith (fun x x_1 ↦ x ++ x_1) (modifyHead (cons a) xs) ys) =
        a :: join (zipWith (fun x x_1 ↦ x ++ x_1) xs ys) := by
    cases xs with | nil => contradiction | cons =>
      

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys✝ : List α
ls : List (List α)
f : List α → List α
as : List α
ys : List (List α)
a : α
hys : ys ≠ []
head✝ : List α
tail✝ : List (List α)
hxs : head✝ :: tail✝ ≠ []
⊢ join (zipWith (fun x x_1 => x ++ x_1) (modifyHead (cons a) (head✝ :: tail✝)) ys) =
    a :: join (zipWith (fun x x_1 => x ++ x_1) (head✝ :: tail✝) ys)

Next tactic:
cases ys with | nil => contradiction | cons => rfl
/-- The original list `L` can be recovered by joining the lists produced by `splitOnP p L`,
interspersed with the elements `L.filter p`. -/
theorem splitOnP_spec (as : List α) :
    join (zipWith (· ++ ·) (splitOnP p as) (((as.filter p).map fun x => [x]) ++ [[]])) = as := by
  induction as with
  | nil => rfl
  | cons a as' ih =>
    rw [splitOnP_cons, filter]
    by_cases h : p a
    · rw [if_pos h, h, map, cons_append, zipWith, nil_append, join, cons_append, cons_inj]
      exact ih
    · rw [if_neg h, eq_false_of_ne_true h, join_zipWith (splitOnP_ne_nil _ _)
        (append_ne_nil_of_ne_nil_right _ [[]] (cons_ne_nil [] [])), cons_inj]
      exact ih
where
  join_zipWith {xs ys : List (List α)} {a : α} (hxs : xs ≠ []) (hys : ys ≠ []) :
      join (zipWith (fun x x_1 ↦ x ++ x_1) (modifyHead (cons a) xs) ys) =
        a :: join (zipWith (fun x x_1 ↦ x ++ x_1) xs ys) := by
    cases xs with | nil => contradiction | cons =>
      cases ys with 

Proof state:
case cons.nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
as : List α
a : α
head✝ : List α
tail✝ : List (List α)
hxs : head✝ :: tail✝ ≠ []
hys : [] ≠ []
⊢ join (zipWith (fun x x_1 => x ++ x_1) (modifyHead (cons a) (head✝ :: tail✝)) []) =
    a :: join (zipWith (fun x x_1 => x ++ x_1) (head✝ :: tail✝) [])

Next tactic:
| nil => contradiction
/-- The original list `L` can be recovered by joining the lists produced by `splitOnP p L`,
interspersed with the elements `L.filter p`. -/
theorem splitOnP_spec (as : List α) :
    join (zipWith (· ++ ·) (splitOnP p as) (((as.filter p).map fun x => [x]) ++ [[]])) = as := by
  induction as with
  | nil => rfl
  | cons a as' ih =>
    rw [splitOnP_cons, filter]
    by_cases h : p a
    · rw [if_pos h, h, map, cons_append, zipWith, nil_append, join, cons_append, cons_inj]
      exact ih
    · rw [if_neg h, eq_false_of_ne_true h, join_zipWith (splitOnP_ne_nil _ _)
        (append_ne_nil_of_ne_nil_right _ [[]] (cons_ne_nil [] [])), cons_inj]
      exact ih
where
  join_zipWith {xs ys : List (List α)} {a : α} (hxs : xs ≠ []) (hys : ys ≠ []) :
      join (zipWith (fun x x_1 ↦ x ++ x_1) (modifyHead (cons a) xs) ys) =
        a :: join (zipWith (fun x x_1 ↦ x ++ x_1) xs ys) := by
    cases xs with | nil => contradiction | cons =>
      cases ys with | nil => 

Proof state:
case cons.nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
as : List α
a : α
head✝ : List α
tail✝ : List (List α)
hxs : head✝ :: tail✝ ≠ []
hys : [] ≠ []
⊢ join (zipWith (fun x x_1 => x ++ x_1) (modifyHead (cons a) (head✝ :: tail✝)) []) =
    a :: join (zipWith (fun x x_1 => x ++ x_1) (head✝ :: tail✝) [])

Next tactic:
contradiction
/-- The original list `L` can be recovered by joining the lists produced by `splitOnP p L`,
interspersed with the elements `L.filter p`. -/
theorem splitOnP_spec (as : List α) :
    join (zipWith (· ++ ·) (splitOnP p as) (((as.filter p).map fun x => [x]) ++ [[]])) = as := by
  induction as with
  | nil => rfl
  | cons a as' ih =>
    rw [splitOnP_cons, filter]
    by_cases h : p a
    · rw [if_pos h, h, map, cons_append, zipWith, nil_append, join, cons_append, cons_inj]
      exact ih
    · rw [if_neg h, eq_false_of_ne_true h, join_zipWith (splitOnP_ne_nil _ _)
        (append_ne_nil_of_ne_nil_right _ [[]] (cons_ne_nil [] [])), cons_inj]
      exact ih
where
  join_zipWith {xs ys : List (List α)} {a : α} (hxs : xs ≠ []) (hys : ys ≠ []) :
      join (zipWith (fun x x_1 ↦ x ++ x_1) (modifyHead (cons a) xs) ys) =
        a :: join (zipWith (fun x x_1 ↦ x ++ x_1) xs ys) := by
    cases xs with | nil => contradiction | cons =>
      cases ys with | nil => contradiction 

Proof state:
case cons.cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
as : List α
a : α
head✝¹ : List α
tail✝¹ : List (List α)
hxs : head✝¹ :: tail✝¹ ≠ []
head✝ : List α
tail✝ : List (List α)
hys : head✝ :: tail✝ ≠ []
⊢ join (zipWith (fun x x_1 => x ++ x_1) (modifyHead (cons a) (head✝¹ :: tail✝¹)) (head✝ :: tail✝)) =
    a :: join (zipWith (fun x x_1 => x ++ x_1) (head✝¹ :: tail✝¹) (head✝ :: tail✝))

Next tactic:
| cons => rfl
/-- The original list `L` can be recovered by joining the lists produced by `splitOnP p L`,
interspersed with the elements `L.filter p`. -/
theorem splitOnP_spec (as : List α) :
    join (zipWith (· ++ ·) (splitOnP p as) (((as.filter p).map fun x => [x]) ++ [[]])) = as := by
  induction as with
  | nil => rfl
  | cons a as' ih =>
    rw [splitOnP_cons, filter]
    by_cases h : p a
    · rw [if_pos h, h, map, cons_append, zipWith, nil_append, join, cons_append, cons_inj]
      exact ih
    · rw [if_neg h, eq_false_of_ne_true h, join_zipWith (splitOnP_ne_nil _ _)
        (append_ne_nil_of_ne_nil_right _ [[]] (cons_ne_nil [] [])), cons_inj]
      exact ih
where
  join_zipWith {xs ys : List (List α)} {a : α} (hxs : xs ≠ []) (hys : ys ≠ []) :
      join (zipWith (fun x x_1 ↦ x ++ x_1) (modifyHead (cons a) xs) ys) =
        a :: join (zipWith (fun x x_1 ↦ x ++ x_1) xs ys) := by
    cases xs with | nil => contradiction | cons =>
      cases ys with | nil => contradiction | cons => 

Proof state:
case cons.cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
as : List α
a : α
head✝¹ : List α
tail✝¹ : List (List α)
hxs : head✝¹ :: tail✝¹ ≠ []
head✝ : List α
tail✝ : List (List α)
hys : head✝ :: tail✝ ≠ []
⊢ join (zipWith (fun x x_1 => x ++ x_1) (modifyHead (cons a) (head✝¹ :: tail✝¹)) (head✝ :: tail✝)) =
    a :: join (zipWith (fun x x_1 => x ++ x_1) (head✝¹ :: tail✝¹) (head✝ :: tail✝))

Next tactic:
rfl
/-- The original list `L` can be recovered by joining the lists produced by `splitOnP p L`,
interspersed with the elements `L.filter p`. -/
theorem splitOnP_spec (as : List α) :
    join (zipWith (· ++ ·) (splitOnP p as) (((as.filter p).map fun x => [x]) ++ [[]])) = as := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
as : List α
⊢ join (zipWith (fun x x_1 => x ++ x_1) (splitOnP p as) (map (fun x => [x]) (filter p as) ++ [[]])) = as

Next tactic:
induction as with
  | nil => rfl
  | cons a as' ih =>
    rw [splitOnP_cons, filter]
    by_cases h : p a
    · rw [if_pos h, h, map, cons_append, zipWith, nil_append, join, cons_append, cons_inj]
      exact ih
    · rw [if_neg h, eq_false_of_ne_true h, join_zipWith (splitOnP_ne_nil _ _)
        (append_ne_nil_of_ne_nil_right _ [[]] (cons_ne_nil [] [])), cons_inj]
      exact ih
/-- The original list `L` can be recovered by joining the lists produced by `splitOnP p L`,
interspersed with the elements `L.filter p`. -/
theorem splitOnP_spec (as : List α) :
    join (zipWith (· ++ ·) (splitOnP p as) (((as.filter p).map fun x => [x]) ++ [[]])) = as := by
  induction as with
  

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
⊢ join (zipWith (fun x x_1 => x ++ x_1) (splitOnP p []) (map (fun x => [x]) (filter p []) ++ [[]])) = []

Next tactic:
| nil => rfl
/-- The original list `L` can be recovered by joining the lists produced by `splitOnP p L`,
interspersed with the elements `L.filter p`. -/
theorem splitOnP_spec (as : List α) :
    join (zipWith (· ++ ·) (splitOnP p as) (((as.filter p).map fun x => [x]) ++ [[]])) = as := by
  induction as with
  | nil => 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
⊢ join (zipWith (fun x x_1 => x ++ x_1) (splitOnP p []) (map (fun x => [x]) (filter p []) ++ [[]])) = []

Next tactic:
rfl
/-- The original list `L` can be recovered by joining the lists produced by `splitOnP p L`,
interspersed with the elements `L.filter p`. -/
theorem splitOnP_spec (as : List α) :
    join (zipWith (· ++ ·) (splitOnP p as) (((as.filter p).map fun x => [x]) ++ [[]])) = as := by
  induction as with
  | nil => rfl
  

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
a : α
as' : List α
ih : join (zipWith (fun x x_1 => x ++ x_1) (splitOnP p as') (map (fun x => [x]) (filter p as') ++ [[]])) = as'
⊢ join (zipWith (fun x x_1 => x ++ x_1) (splitOnP p (a :: as')) (map (fun x => [x]) (filter p (a :: as')) ++ [[]])) =
    a :: as'

Next tactic:
| cons a as' ih =>
    rw [splitOnP_cons, filter]
    by_cases h : p a
    · rw [if_pos h, h, map, cons_append, zipWith, nil_append, join, cons_append, cons_inj]
      exact ih
    · rw [if_neg h, eq_false_of_ne_true h, join_zipWith (splitOnP_ne_nil _ _)
        (append_ne_nil_of_ne_nil_right _ [[]] (cons_ne_nil [] [])), cons_inj]
      exact ih
/-- The original list `L` can be recovered by joining the lists produced by `splitOnP p L`,
interspersed with the elements `L.filter p`. -/
theorem splitOnP_spec (as : List α) :
    join (zipWith (· ++ ·) (splitOnP p as) (((as.filter p).map fun x => [x]) ++ [[]])) = as := by
  induction as with
  | nil => rfl
  | cons a as' ih =>
    

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
a : α
as' : List α
ih : join (zipWith (fun x x_1 => x ++ x_1) (splitOnP p as') (map (fun x => [x]) (filter p as') ++ [[]])) = as'
⊢ join (zipWith (fun x x_1 => x ++ x_1) (splitOnP p (a :: as')) (map (fun x => [x]) (filter p (a :: as')) ++ [[]])) =
    a :: as'

Next tactic:
rw [splitOnP_cons, filter]
/-- The original list `L` can be recovered by joining the lists produced by `splitOnP p L`,
interspersed with the elements `L.filter p`. -/
theorem splitOnP_spec (as : List α) :
    join (zipWith (· ++ ·) (splitOnP p as) (((as.filter p).map fun x => [x]) ++ [[]])) = as := by
  induction as with
  | nil => rfl
  | cons a as' ih =>
    rw [splitOnP_cons, filter]
    

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
a : α
as' : List α
ih : join (zipWith (fun x x_1 => x ++ x_1) (splitOnP p as') (map (fun x => [x]) (filter p as') ++ [[]])) = as'
⊢ join
      (zipWith (fun x x_1 => x ++ x_1)
        (if p a = true then [] :: splitOnP p as' else modifyHead (cons a) (splitOnP p as'))
        (map (fun x => [x])
            (match p a with
            | true => a :: filter p as'
            | false => filter p as') ++
          [[]])) =
    a :: as'

Next tactic:
by_cases h : p a
/-- The original list `L` can be recovered by joining the lists produced by `splitOnP p L`,
interspersed with the elements `L.filter p`. -/
theorem splitOnP_spec (as : List α) :
    join (zipWith (· ++ ·) (splitOnP p as) (((as.filter p).map fun x => [x]) ++ [[]])) = as := by
  induction as with
  | nil => rfl
  | cons a as' ih =>
    rw [splitOnP_cons, filter]
    by_cases h : p a
    · 

Proof state:
case pos
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
a : α
as' : List α
ih : join (zipWith (fun x x_1 => x ++ x_1) (splitOnP p as') (map (fun x => [x]) (filter p as') ++ [[]])) = as'
h : p a = true
⊢ join
      (zipWith (fun x x_1 => x ++ x_1)
        (if p a = true then [] :: splitOnP p as' else modifyHead (cons a) (splitOnP p as'))
        (map (fun x => [x])
            (match p a with
            | true => a :: filter p as'
            | false => filter p as') ++
          [[]])) =
    a :: as'

Next tactic:
rw [if_pos h, h, map, cons_append, zipWith, nil_append, join, cons_append, cons_inj]
/-- The original list `L` can be recovered by joining the lists produced by `splitOnP p L`,
interspersed with the elements `L.filter p`. -/
theorem splitOnP_spec (as : List α) :
    join (zipWith (· ++ ·) (splitOnP p as) (((as.filter p).map fun x => [x]) ++ [[]])) = as := by
  induction as with
  | nil => rfl
  | cons a as' ih =>
    rw [splitOnP_cons, filter]
    by_cases h : p a
    · rw [if_pos h, h, map, cons_append, zipWith, nil_append, join, cons_append, cons_inj]
      

Proof state:
case pos
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
a : α
as' : List α
ih : join (zipWith (fun x x_1 => x ++ x_1) (splitOnP p as') (map (fun x => [x]) (filter p as') ++ [[]])) = as'
h : p a = true
⊢ [] ++ join (zipWith (fun x x_1 => x ++ x_1) (splitOnP p as') (map (fun x => [x]) (filter p as') ++ [[]])) = as'

Next tactic:
exact ih
/-- The original list `L` can be recovered by joining the lists produced by `splitOnP p L`,
interspersed with the elements `L.filter p`. -/
theorem splitOnP_spec (as : List α) :
    join (zipWith (· ++ ·) (splitOnP p as) (((as.filter p).map fun x => [x]) ++ [[]])) = as := by
  induction as with
  | nil => rfl
  | cons a as' ih =>
    rw [splitOnP_cons, filter]
    by_cases h : p a
    · rw [if_pos h, h, map, cons_append, zipWith, nil_append, join, cons_append, cons_inj]
      exact ih
    · 

Proof state:
case neg
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
a : α
as' : List α
ih : join (zipWith (fun x x_1 => x ++ x_1) (splitOnP p as') (map (fun x => [x]) (filter p as') ++ [[]])) = as'
h : ¬p a = true
⊢ join
      (zipWith (fun x x_1 => x ++ x_1)
        (if p a = true then [] :: splitOnP p as' else modifyHead (cons a) (splitOnP p as'))
        (map (fun x => [x])
            (match p a with
            | true => a :: filter p as'
            | false => filter p as') ++
          [[]])) =
    a :: as'

Next tactic:
rw [if_neg h, eq_false_of_ne_true h, join_zipWith (splitOnP_ne_nil _ _)
        (append_ne_nil_of_ne_nil_right _ [[]] (cons_ne_nil [] [])), cons_inj]
/-- The original list `L` can be recovered by joining the lists produced by `splitOnP p L`,
interspersed with the elements `L.filter p`. -/
theorem splitOnP_spec (as : List α) :
    join (zipWith (· ++ ·) (splitOnP p as) (((as.filter p).map fun x => [x]) ++ [[]])) = as := by
  induction as with
  | nil => rfl
  | cons a as' ih =>
    rw [splitOnP_cons, filter]
    by_cases h : p a
    · rw [if_pos h, h, map, cons_append, zipWith, nil_append, join, cons_append, cons_inj]
      exact ih
    · rw [if_neg h, eq_false_of_ne_true h, join_zipWith (splitOnP_ne_nil _ _)
        (append_ne_nil_of_ne_nil_right _ [[]] (cons_ne_nil [] [])), cons_inj]
      

Proof state:
case neg
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
xs ys : List α
ls : List (List α)
f : List α → List α
a : α
as' : List α
ih : join (zipWith (fun x x_1 => x ++ x_1) (splitOnP p as') (map (fun x => [x]) (filter p as') ++ [[]])) = as'
h : ¬p a = true
⊢ join
      (zipWith (fun x x_1 => x ++ x_1) (splitOnP p as')
        (map (fun x => [x])
            (match false with
            | true => a :: filter p as'
            | false => filter p as') ++
          [[]])) =
    as'

Next tactic:
exact ih