Zulip Chat Archive

Stream: lean4

Topic: Question about termination


Ben Selfridge (Mar 23 2025 at 18:55):

Hello,

Consider the following MRE:

section
inductive Var
| A : Var

inductive A
| Var : A
| A : A  A

def subst (aₓ : A) (a : A) : A := match a with
  | A.Var => aₓ
  | A.A a' => subst aₓ a'
end

def subst' (aₓ : A) (a : A) : A := match (true, a) with
  | (true, A.Var) => aₓ
  | (true, A.A a') => subst' aₓ a'
  | (false, _) => a
end

Lean can prove termination for subst not subst'. I was wondering if anyone could explain why.

Ben Selfridge (Mar 23 2025 at 19:01):

Followup.

I tried the obvious termination_by a, and it failed to go through (unsurprisingly). When I tried to add a decreasing_by clause, the context did not know that a = A.a a'. It had no information about either variable.

Henrik Böving (Mar 23 2025 at 19:06):

You can do it manually:

inductive Var
| A : Var

inductive A
| Var : A
| A : A  A

def subst (aₓ : A) (a : A) : A :=
  match a with
  | A.Var => aₓ
  | A.A a' => subst aₓ a'

def subst' (aₓ : A) (a : A) : A :=
  match h:(true, a) with
  | (true, A.Var) => aₓ
  | (true, A.A a') =>
    have : sizeOf a' < sizeOf a := by
      simp at h
      rw [h]
      simp
    subst' aₓ a'
  | (false, _) => a
termination_by a

Ben Selfridge (Mar 23 2025 at 19:06):

Thanks!

Henrik Böving (Mar 23 2025 at 19:07):

It is a bit unfortunate it can't guess this on it's own though

Ben Selfridge (Mar 23 2025 at 19:07):

It is!

Henrik Böving (Mar 23 2025 at 19:09):

I guess you could open an issue about it so we don't forget about it

Ben Selfridge (Mar 23 2025 at 19:21):

Just did that. But I'm glad I asked, because I didn't realize you could do termination proofs within the clauses of a function definition like this. Super cool!


Last updated: May 02 2025 at 03:31 UTC