lean4-htt/tests/lean/run/nested_inductive.lean
Kim Morrison a4fda010f3
feat: Array/Option.unattach (#5586)
More support for automatically removing `.attach`, for `Array` and
`Option`.
2024-10-03 07:29:00 +00:00

101 lines
2.7 KiB
Text

/-! # Nested inductive types
See "Recursion through lists and arrays" in https://blog.lean-lang.org/blog/2024-9-1-lean-4110/
This test file exercises the `attach`/`unattach` API.
-/
namespace List
inductive Tree where | node : List Tree → Tree
namespace Tree
def rev : Tree → Tree
| node ts => .node (ts.attach.reverse.map (fun ⟨t, _⟩ => t.rev))
-- Note that `simp` now automatically removes the `attach`.
@[simp] theorem rev_def (ts : List Tree) :
Tree.rev (.node ts) = .node (ts.reverse.map rev) := by
simp [Tree.rev]
-- Variant with an explicit `have`, rather than using a pattern match.
def rev' : Tree → Tree
| node ts => .node (ts.attach.reverse.map (fun t => have := t.2; t.1.rev'))
@[simp] theorem rev'_def (ts : List Tree) :
Tree.rev' (.node ts) = .node (ts.reverse.map rev') := by
simp [Tree.rev']
/-- Define `size` using a `foldl` over `attach`. -/
def size : Tree → Nat
| node ts => 1 + ts.attach.foldl (fun acc ⟨t, _⟩ => acc + t.size) 0
@[simp] theorem size_def (ts : List Tree) :
size (.node ts) = 1 + ts.foldl (fun acc t => acc + t.size) 0 := by
simp [size]
/-- Define `depth` using a `foldr` over `attach`. -/
def depth : Tree → Nat
| node ts => 1 + ts.attach.foldr (fun ⟨t, _⟩ acc => acc + t.depth) 0
@[simp] theorem depth_def (ts : List Tree) :
depth (.node ts) = 1 + ts.foldr (fun t acc => acc + t.depth) 0 := by
simp [depth]
end Tree
end List
namespace Array
inductive Tree where | node : Array Tree → Tree
namespace Tree
def rev : Tree → Tree
| node ts => .node (ts.attach.reverse.map (fun ⟨t, _⟩ => t.rev))
-- Note that `simp` now automatically removes the `attach`.
@[simp] theorem rev_def (ts : Array Tree) :
Tree.rev (.node ts) = .node (ts.reverse.map rev) := by
simp [Tree.rev]
/-- Define `size` using a `foldl` over `attach`. -/
def size : Tree → Nat
| node ts => 1 + ts.attach.foldl (fun acc ⟨t, _⟩ => acc + t.size) 0
@[simp] theorem size_def (ts : Array Tree) :
size (.node ts) = 1 + ts.foldl (fun acc t => acc + t.size) 0 := by
simp [size]
/-- Define `depth` using a `foldr` over `attach`. -/
def depth : Tree → Nat
| node ts => 1 + ts.attach.foldr (fun ⟨t, _⟩ acc => acc + t.depth) 0
@[simp] theorem depth_def (ts : Array Tree) :
depth (.node ts) = 1 + ts.foldr (fun t acc => acc + t.depth) 0 := by
simp [depth]
end Tree
end Array
namespace Option
inductive Tree where | node : Option Tree → Option Tree → Tree
namespace Tree
def rev : Tree → Tree
| node l r => .node (r.attach.map fun ⟨r, _⟩ => r.rev) (l.attach.map fun ⟨l, _⟩ => l.rev)
@[simp] theorem rev_def (l r : Option Tree) :
Tree.rev (.node l r) = .node (r.map rev) (l.map rev) := by
simp [Tree.rev]
end Tree
end Option