inductive TreeNode where | mkLeaf (name : String) : TreeNode | mkNode (name : String) (children : List TreeNode) : TreeNode def treeToList (t : TreeNode) : List String := match t with | .mkLeaf name => [name] | .mkNode name children => Id.run do let mut r := [name] for h : child in children do -- We will not this the following `have` in the future have : sizeOf child < 1 + sizeOf name + sizeOf children := Nat.lt_trans (List.sizeOf_lt_of_mem h) (by simp +arith) r := r ++ treeToList child return r @[simp] theorem treeToList_eq (name : String) (children : List TreeNode) : treeToList (.mkNode name children) = name :: List.flatten (children.map treeToList) := by simp [treeToList] mutual def numNames : TreeNode → Nat | .mkLeaf _ => 1 | .mkNode _ cs => 1 + numNamesLst cs def numNamesLst : List TreeNode → Nat | [] => 0 | a :: as => numNames a + numNamesLst as end theorem length_treeToList_eq_numNames (t : TreeNode) : (treeToList t).length = numNames t := by match t with | .mkLeaf .. => simp [treeToList, numNames] | .mkNode _ cs => simp +arith [numNames, helper cs] where helper (cs : List TreeNode) : (cs.map treeToList).flatten.length = numNamesLst cs := by match cs with | [] => simp [List.flatten, numNamesLst] | c::cs' => simp [List.flatten, List.map, numNamesLst, length_treeToList_eq_numNames c, helper cs']