Zulip Chat Archive

Stream: Is there code for X?

Topic: prove termination of a function defined by `let rec`


Asei Inoue (Mar 24 2024 at 05:31):

I'm working on Lean 99, which is lean translation of Haskell 99. This is Problem 24.

Why does the proof of termination fail while fuel trick is used? Can it be rewritten so that termination is clear without using fuel?

/-- Draw `N` different random numbers from the set `1..M`. -/
def diffSelect (count range : Nat) : IO (List Nat) :=
  if count > range then
    dbg_trace s!"can't draw {count} different numbers from 1..{range}"
    pure []
  else
    let rec loop (count : Nat) (acc : List Nat) (fuel : Nat) : IO (List Nat) := do
      match count, fuel with
      | 0, _ => pure acc
      | _, 0 =>
        dbg_trace "out of fuel!"
        pure []
      | _, _ =>
        let pick  IO.rand 1 range
        if acc.contains pick then
          loop count acc (fuel - 1) -- failed to prove termination
        else
          loop (count - 1) (pick :: acc) (fuel - 1)
      termination_by fuel
    loop count [] 10000

Kim Morrison (Mar 24 2024 at 06:29):

/-- Draw `N` different random numbers from the set `1..M`. -/
def diffSelect (count range : Nat) : IO (List Nat) :=
  if count > range then
    dbg_trace s!"can't draw {count} different numbers from 1..{range}"
    pure []
  else
    let rec loop (count : Nat) (acc : List Nat) (fuel : Nat) : IO (List Nat) := do
      match count, fuel with
      | 0, _ => pure acc
      | _, 0 =>
        dbg_trace "out of fuel!"
        pure []
      | _, fuel + 1 =>
        let pick  IO.rand 1 range
        if acc.contains pick then
          loop count acc fuel
        else
          loop (count - 1) (pick :: acc) fuel
      termination_by fuel
    loop count [] 10000

Asei Inoue (Mar 24 2024 at 14:05):

Thanks.


Last updated: May 02 2025 at 03:31 UTC