Zulip Chat Archive
Stream: lean4
Topic: structural recursion cannot be used
Kyle Miller (Jan 24 2022 at 05:59):
How can I show that nodes
terminates in the following example?
inductive Foo
| a : Foo → Foo
| b : String × Foo → Foo
| c : Foo
namespace Foo
def nodes : Foo → Nat
| a x => x.nodes + 1
| b _ => 1
| c => 1
/-
fail to show termination for
Foo.nodes
with errors
structural recursion cannot be used
'termination_by' modifier missing
-/
end Foo
Kyle Miller (Jan 24 2022 at 06:01):
Changing it to the following, Lean's able to see that the function terminates, but in what I'm actually doing, b
has a List (String × Foo)
instead.
inductive Foo
| a : Foo → Foo
| b : String → Foo → Foo
| c : Foo
namespace Foo
def nodes : Foo → Nat
| a x => x.nodes + 1
| b _ _ => 1
| c => 1
end Foo
Mario Carneiro (Jan 24 2022 at 06:04):
You should try termination_by
Kyle Miller (Jan 24 2022 at 06:06):
Mario Carneiro said:
You should try
termination_by
... Yes, I read the error message and I messed around with it for a bit, looking up uses of termination_by
in the lean4 repository, but I couldn't see how to use it for this.
Mario Carneiro (Jan 24 2022 at 06:09):
worst case scenario I believe you can use the Foo
recursor directly, but hopefully the autogenerated sizeof instance works
Kyle Miller (Jan 24 2022 at 06:25):
Thanks for the sizeOf
pointer.
Is there a simpler way to write this than what I did below? (Are there plans to make writing recursive functions like this easier?)
inductive Foo
| a : Foo → Foo
| b : String × Foo → Foo
| c : Foo
namespace Foo
def nodes (f : Foo) : Nat :=
match f with
| a x =>
have : sizeOf x < 1 + sizeOf x := by
rw [Nat.add_comm]
apply Nat.le_refl
x.nodes + 1
| b _ => 1
| c => 1
termination_by _ => sizeOf f
end Foo
Last updated: Dec 20 2023 at 11:08 UTC