The following example type checks in Lean 4, but I am confused why the termination_by declaration is required.
import Mathlib.Tactic.Linarith
def Idx (n:Nat) := Fin n
def sum(k:Idx n) : Nat :=
if p:k.val=0 then 0
else
have p : k.val-1 < k.val := (Nat.pred_lt p);
let km1 : Idx n := {val:=k.val-1,isLt:=(by linarith [k.isLt])};
1+(sum km1)
termination_by sum k => k.val
Specifically, a very similar example does not require it:
def sum2(k:Fin n) : Nat :=
if p:k.val=0 then 0
else
have p : k.val-1 < k.val := (Nat.pred_lt p);
let km1 : Fin n := {val:=k.val-1,isLt:=(by linarith [k.isLt])};
1+(sum2 km1)
Obviously, it has something to do with the fact that I've wrapped the Fin n with Idx n. I tried adding a @[simp] annotation, but that didn't help.
(also am interested in whether the example can be improved)
The problem is that by writing
def Idx (n:Nat) := Fin n
that type class search won’t find instances for Idx that it would find for Fin, in particular not the SizeOf instance used for recursion.
As @jthulhu mentioned, using abbrev is the appropriate fix for this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With