Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Termination for Wrapped `Fin n` in Lean4

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)

like image 945
redjamjar Avatar asked Jan 20 '26 12:01

redjamjar


1 Answers

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.

like image 135
Joachim Breitner Avatar answered Jan 23 '26 14:01

Joachim Breitner



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!