Theorem: Lean.Data.AC.Context.evalList_mergeIdem
File: src/lean/Init/Data/AC.lean

tactic: have h : IsIdempotent ctx.op := by simp [ContextInformation.isIdem, Option.isSome] at h; cases h₂ : ctx.idem <;> simp [h₂] at h; assumption
state_before: α : Sort u_1
ctx : Context α
h : ContextInformation.isIdem ctx = true
e : List Nat
⊢ evalList α ctx (mergeIdem e) = evalList α ctx e

tactic: induction e using List.two_step_induction with
| empty => rfl
| single => rfl
| step x y ys ih =>
  cases ys with
  | nil =>
    simp [mergeIdem, mergeIdem.loop]
    split
    case inl h₂ => simp [evalList, h₂, h.1, EvalInformation.evalOp]
    rfl
  | cons z zs =>
    by_cases h₂ : x = y
    case inl =>
      rw [h₂, mergeIdem_head, ih]
      simp [evalList, ←ctx.assoc.1, h.1, EvalInformation.evalOp]
    case inr =>
      rw [mergeIdem_head2]
      by_cases h₃ : y = z
      case inl =>
        simp [mergeIdem_head, h₃, evalList]
        cases h₄ : mergeIdem (z :: zs) with
        | nil => apply absurd h₄; apply mergeIdem_nonEmpty; simp
        | cons u us => simp_all [mergeIdem, mergeIdem.loop, evalList]
      case inr =>
        simp [mergeIdem_head2, h₃, evalList] at *
        rw [ih]
      assumption
state_before: α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
e : List Nat
h : IsIdempotent ctx.op
⊢ evalList α ctx (mergeIdem e) = evalList α ctx e

tactic: simp [ContextInformation.isIdem, Option.isSome] at h
state_before: α : Sort u_1
ctx : Context α
h : ContextInformation.isIdem ctx = true
e : List Nat
⊢ IsIdempotent ctx.op

tactic: cases h₂ : ctx.idem <;> simp [h₂] at h
state_before: α : Sort u_1
ctx : Context α
h :
  (match ctx.idem with
    | some val => true
    | none => false) =
    true
e : List Nat
⊢ IsIdempotent ctx.op

tactic: assumption
state_before: case some
α : Sort u_1
ctx : Context α
e : List Nat
val✝ : IsIdempotent ctx.op
h₂ : ctx.idem = some val✝
h : True
⊢ IsIdempotent ctx.op

tactic: rfl
state_before: case empty
α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
⊢ evalList α ctx (mergeIdem []) = evalList α ctx []

tactic: rfl
state_before: case single
α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
a✝ : Nat
⊢ evalList α ctx (mergeIdem [a✝]) = evalList α ctx [a✝]

tactic: cases ys with
| nil =>
  simp [mergeIdem, mergeIdem.loop]
  split
  case inl h₂ => simp [evalList, h₂, h.1, EvalInformation.evalOp]
  rfl
| cons z zs =>
  by_cases h₂ : x = y
  case inl =>
    rw [h₂, mergeIdem_head, ih]
    simp [evalList, ←ctx.assoc.1, h.1, EvalInformation.evalOp]
  case inr =>
    rw [mergeIdem_head2]
    by_cases h₃ : y = z
    case inl =>
      simp [mergeIdem_head, h₃, evalList]
      cases h₄ : mergeIdem (z :: zs) with
      | nil => apply absurd h₄; apply mergeIdem_nonEmpty; simp
      | cons u us => simp_all [mergeIdem, mergeIdem.loop, evalList]
    case inr =>
      simp [mergeIdem_head2, h₃, evalList] at *
      rw [ih]
    assumption
state_before: case step
α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y : Nat
ys : List Nat
ih : evalList α ctx (mergeIdem (y :: ys)) = evalList α ctx (y :: ys)
⊢ evalList α ctx (mergeIdem (x :: y :: ys)) = evalList α ctx (x :: y :: ys)

tactic: simp [mergeIdem, mergeIdem.loop]
state_before: case step.nil
α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y : Nat
ih : evalList α ctx (mergeIdem [y]) = evalList α ctx [y]
⊢ evalList α ctx (mergeIdem [x, y]) = evalList α ctx [x, y]

tactic: split
state_before: case step.nil
α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y : Nat
ih : evalList α ctx (mergeIdem [y]) = evalList α ctx [y]
⊢ evalList α ctx (if x = y then [x] else [x, y]) = evalList α ctx [x, y]

tactic: case inl h₂ => simp [evalList, h₂, h.1, EvalInformation.evalOp]
state_before: case step.nil.inl
α : Sort u_1
ctx : Context α
h✝¹ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y : Nat
ih : evalList α ctx (mergeIdem [y]) = evalList α ctx [y]
h✝ : x = y
⊢ evalList α ctx [x] = evalList α ctx [x, y]

case step.nil.inr
α : Sort u_1
ctx : Context α
h✝¹ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y : Nat
ih : evalList α ctx (mergeIdem [y]) = evalList α ctx [y]
h✝ : ¬x = y
⊢ evalList α ctx [x, y] = evalList α ctx [x, y]

tactic: rfl
state_before: case step.nil.inr
α : Sort u_1
ctx : Context α
h✝¹ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y : Nat
ih : evalList α ctx (mergeIdem [y]) = evalList α ctx [y]
h✝ : ¬x = y
⊢ evalList α ctx [x, y] = evalList α ctx [x, y]

tactic: simp [evalList, h₂, h.1, EvalInformation.evalOp]
state_before: α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y : Nat
ih : evalList α ctx (mergeIdem [y]) = evalList α ctx [y]
h₂ : x = y
⊢ evalList α ctx [x] = evalList α ctx [x, y]

tactic: by_cases h₂ : x = y
state_before: case step.cons
α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
⊢ evalList α ctx (mergeIdem (x :: y :: z :: zs)) = evalList α ctx (x :: y :: z :: zs)

tactic: case inl =>
  rw [h₂, mergeIdem_head, ih]
  simp [evalList, ←ctx.assoc.1, h.1, EvalInformation.evalOp]
state_before: case step.cons.inl
α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
h₂ : x = y
⊢ evalList α ctx (mergeIdem (x :: y :: z :: zs)) = evalList α ctx (x :: y :: z :: zs)

case step.cons.inr
α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
h₂ : ¬x = y
⊢ evalList α ctx (mergeIdem (x :: y :: z :: zs)) = evalList α ctx (x :: y :: z :: zs)

tactic: case inr =>
  rw [mergeIdem_head2]
  by_cases h₃ : y = z
  case inl =>
    simp [mergeIdem_head, h₃, evalList]
    cases h₄ : mergeIdem (z :: zs) with
    | nil => apply absurd h₄; apply mergeIdem_nonEmpty; simp
    | cons u us => simp_all [mergeIdem, mergeIdem.loop, evalList]
  case inr =>
    simp [mergeIdem_head2, h₃, evalList] at *
    rw [ih]
  assumption
state_before: case step.cons.inr
α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
h₂ : ¬x = y
⊢ evalList α ctx (mergeIdem (x :: y :: z :: zs)) = evalList α ctx (x :: y :: z :: zs)

tactic: rw [h₂, mergeIdem_head, ih]
state_before: α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
h₂ : x = y
⊢ evalList α ctx (mergeIdem (x :: y :: z :: zs)) = evalList α ctx (x :: y :: z :: zs)

tactic: simp [evalList, ←ctx.assoc.1, h.1, EvalInformation.evalOp]
state_before: α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
h₂ : x = y
⊢ evalList α ctx (y :: z :: zs) = evalList α ctx (y :: y :: z :: zs)

tactic: rw [mergeIdem_head2]
state_before: α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
h₂ : ¬x = y
⊢ evalList α ctx (mergeIdem (x :: y :: z :: zs)) = evalList α ctx (x :: y :: z :: zs)

tactic: by_cases h₃ : y = z
state_before: α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
h₂ : ¬x = y
⊢ evalList α ctx (x :: mergeIdem (y :: z :: zs)) = evalList α ctx (x :: y :: z :: zs)

α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
h₂ : ¬x = y
⊢ x ≠ y

tactic: case inl =>
  simp [mergeIdem_head, h₃, evalList]
  cases h₄ : mergeIdem (z :: zs) with
  | nil => apply absurd h₄; apply mergeIdem_nonEmpty; simp
  | cons u us => simp_all [mergeIdem, mergeIdem.loop, evalList]
state_before: case inl
α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
h₂ : ¬x = y
h₃ : y = z
⊢ evalList α ctx (x :: mergeIdem (y :: z :: zs)) = evalList α ctx (x :: y :: z :: zs)

case inr
α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
h₂ : ¬x = y
h₃ : ¬y = z
⊢ evalList α ctx (x :: mergeIdem (y :: z :: zs)) = evalList α ctx (x :: y :: z :: zs)

α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
h₂ : ¬x = y
⊢ x ≠ y

tactic: case inr =>
  simp [mergeIdem_head2, h₃, evalList] at *
  rw [ih]
state_before: case inr
α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
h₂ : ¬x = y
h₃ : ¬y = z
⊢ evalList α ctx (x :: mergeIdem (y :: z :: zs)) = evalList α ctx (x :: y :: z :: zs)

α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
h₂ : ¬x = y
⊢ x ≠ y

tactic: assumption
state_before: α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
h₂ : ¬x = y
⊢ x ≠ y

tactic: simp [mergeIdem_head, h₃, evalList]
state_before: α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
h₂ : ¬x = y
h₃ : y = z
⊢ evalList α ctx (x :: mergeIdem (y :: z :: zs)) = evalList α ctx (x :: y :: z :: zs)

tactic: cases h₄ : mergeIdem (z :: zs) with
| nil => apply absurd h₄; apply mergeIdem_nonEmpty; simp
| cons u us => simp_all [mergeIdem, mergeIdem.loop, evalList]
state_before: α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
h₂ : ¬x = y
h₃ : y = z
⊢ evalList α ctx (x :: mergeIdem (z :: zs)) =
    EvalInformation.evalOp ctx (EvalInformation.evalVar ctx x)
      (EvalInformation.evalOp ctx (EvalInformation.evalVar ctx z) (evalList α ctx (z :: zs)))

tactic: apply absurd h₄
state_before: case nil
α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
h₂ : ¬x = y
h₃ : y = z
h₄ : mergeIdem (z :: zs) = []
⊢ evalList α ctx [x] =
    EvalInformation.evalOp ctx (EvalInformation.evalVar ctx x)
      (EvalInformation.evalOp ctx (EvalInformation.evalVar ctx z) (evalList α ctx (z :: zs)))

tactic: apply mergeIdem_nonEmpty
state_before: case nil
α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
h₂ : ¬x = y
h₃ : y = z
h₄ : mergeIdem (z :: zs) = []
⊢ ¬mergeIdem (z :: zs) = []

tactic: simp
state_before: case nil.h
α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
h₂ : ¬x = y
h₃ : y = z
h₄ : mergeIdem (z :: zs) = []
⊢ z :: zs ≠ []

tactic: simp_all [mergeIdem, mergeIdem.loop, evalList]
state_before: case cons
α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
h₂ : ¬x = y
h₃ : y = z
u : Nat
us : List Nat
h₄ : mergeIdem (z :: zs) = u :: us
⊢ evalList α ctx (x :: u :: us) =
    EvalInformation.evalOp ctx (EvalInformation.evalVar ctx x)
      (EvalInformation.evalOp ctx (EvalInformation.evalVar ctx z) (evalList α ctx (z :: zs)))

tactic: simp [mergeIdem_head2, h₃, evalList] at *
state_before: α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
ih : evalList α ctx (mergeIdem (y :: z :: zs)) = evalList α ctx (y :: z :: zs)
h₂ : ¬x = y
h₃ : ¬y = z
⊢ evalList α ctx (x :: mergeIdem (y :: z :: zs)) = evalList α ctx (x :: y :: z :: zs)

tactic: rw [ih]
state_before: α : Sort u_1
ctx : Context α
h✝ : ContextInformation.isIdem ctx = true
h : IsIdempotent ctx.op
x y z : Nat
zs : List Nat
h₂ : ¬x = y
ih :
  evalList α ctx (y :: mergeIdem (z :: zs)) =
    EvalInformation.evalOp ctx (EvalInformation.evalVar ctx y) (evalList α ctx (z :: zs))
h₃ : True
⊢ EvalInformation.evalOp ctx (EvalInformation.evalVar ctx x) (evalList α ctx (y :: mergeIdem (z :: zs))) =
    EvalInformation.evalOp ctx (EvalInformation.evalVar ctx x)
      (EvalInformation.evalOp ctx (EvalInformation.evalVar ctx y) (evalList α ctx (z :: zs)))