This PR reworks the `simp` set around the `Id` monad, to not elide or unfold `pure` and `Id.run` In particular, it stops encoding the "defeq abuse" of `Id X = X` in the statements of theorems, instead using `Id.run` and `pure` to pass back and forth between these two spellings. Often when writing these with `pure`, they generalize to other lawful monads; though such changes were split off to other PRs. This fixes the problem with the current simp set where `Id.run (pure x)` is simplified to `Id.run x`, instead of the desirable `x`. This is particularly bad because the` x` is sometimes inferred with type `Id X` instead of `X`, which prevents other `simp` lemmas about `X` from firing. Making `Id` reducible instead is not an option, as then the `Monad` instances would have nothing to key on. --------- Co-authored-by: Sebastian Graf <sg@lean-fro.org> Co-authored-by: Kim Morrison <kim@tqft.net> Co-authored-by: Paul Reichert <6992158+datokrat@users.noreply.github.com>
36 lines
1.4 KiB
Text
36 lines
1.4 KiB
Text
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']
|