inductive LazyList (α : Type u) | nil : LazyList α | cons (hd : α) (tl : LazyList α) : LazyList α | delayed (t : Thunk (LazyList α)) : LazyList α namespace LazyList def length : LazyList α → Nat | nil => 0 | cons _ as => length as + 1 | delayed as => length as.get def force : LazyList α → Option (α × LazyList α) | delayed as => force as.get | nil => none | cons a as => some (a,as) end LazyList def rotate (f : LazyList τ) (r : List τ) (a : LazyList τ) (h : f.length + 1 = r.length) : LazyList τ := match r with | List.nil => False.elim (by simp +arith [LazyList.length] at h) | y::r' => match f.force with | none => LazyList.cons y a | some (x, f') => LazyList.cons x (rotate f' r' (LazyList.cons y a) (sorry)) theorem rotate_inv {F : LazyList τ} {R : List τ} : (h : F.length + 1 = R.length) → (rotate F R nil h).length = F.length + R.length := by match F with | LazyList.nil => intro h; unfold rotate; sorry | LazyList.cons Fh Ft => sorry | LazyList.delayed Ft => sorry def LazyList.ind {α : Type u} {motive : LazyList α → Sort v} (nil : motive LazyList.nil) (cons : (hd : α) → (tl : LazyList α) → motive tl → motive (LazyList.cons hd tl)) (delayed : (t : Thunk (LazyList α)) → motive t.get → motive (LazyList.delayed t)) (t : LazyList α) : motive t := match t with | LazyList.nil => nil | LazyList.cons h t => cons h t (ind nil cons delayed t) | LazyList.delayed t => delayed t (ind nil cons delayed t.get) -- Remark: Lean used well-founded recursion behind the scenes to define LazyList.ind /-- trace: case cons τ : Type u_1 nil : LazyList τ R : List τ h : τ t : LazyList τ ih : ∀ (h : t.length + 1 = R.length), (rotate t R nil h).length = t.length + R.length ⊢ ∀ (h_1 : (LazyList.cons h t).length + 1 = R.length), (rotate (LazyList.cons h t) R nil h_1).length = (LazyList.cons h t).length + R.length --- trace: case delayed τ : Type u_1 nil : LazyList τ R : List τ t : Thunk (LazyList τ) a✝ : ∀ (h : t.get.length + 1 = R.length), (rotate t.get R nil h).length = t.get.length + R.length ⊢ ∀ (h : (LazyList.delayed t).length + 1 = R.length), (rotate (LazyList.delayed t) R nil h).length = (LazyList.delayed t).length + R.length --- warning: declaration uses 'sorry' -/ #guard_msgs in theorem rotate_inv' {F : LazyList τ} {R : List τ} : (h : F.length + 1 = R.length) → (rotate F R nil h).length = F.length + R.length := by induction F using LazyList.ind with | nil => intro h; unfold rotate; sorry | cons h t ih => trace_state; sorry | delayed t => trace_state; sorry