Zulip Chat Archive

Stream: lean4

Topic: recursive function does not get unfolded


Tomas Skrivan (Apr 14 2025 at 21:10):

I have this recursive function

def progress :  (M :   A), Progress M
  | (# x) => by contradiction
  | (ƛ N) => done Value.lambda
  | (L  M) =>
      match progress L with
        | step L_to_L' => step (xi_app_1 L_to_L')
        | done v =>
            match progress M with
              | step M_to_M' => step (xi_app_2 v M_to_M')
              | done w =>
                  match v with
                    | Value.lambda => step (beta w)
  | o => done Value.zero
  | (M +1) =>
      match progress M with
        | step M_to_M' => step (xi_succ M_to_M')
        | done v => done (Value.succ v)
  | (switch L M N) =>
      match progress L with
        | step L_to_L' => step (xi_case L_to_L')
        | done v =>
            match v with
              | Value.zero => step beta_zero
              | Value.succ v => step (beta_succ v)
  | (μ N) => step beta_mu

I'm confused why

example : progress o = done Value.zero := by rfl

does not work. It works if I mark the function with abbrev.

mwe

code

Tomas Skrivan (Apr 14 2025 at 21:12):

cc @Philip Wadler

Yan Yablonovskiy (Apr 15 2025 at 05:34):

(deleted)

Kyle Miller (Apr 15 2025 at 05:42):

If you #print progress and then #print progress._unary, you can see that it's using WellFounded.fix, so it's well-founded recursion. Definitions using well-founded recursion are irreducible.

Here's this week's discussion about the issue: #lean4 > opaque recursion definitions break mergeSort decidability @ 💬

Tomas Skrivan (Apr 15 2025 at 14:16):

Nice, I was wondering if it has something to do with well-founded recursion but had no idea how to check it.


Last updated: May 02 2025 at 03:31 UTC