Zulip Chat Archive

Stream: new members

Topic: Code review: Defining a partial function, then proving total


C7X (Aug 18 2025 at 07:34):

Hi!

I have a minimal working example here where I define a partial function expand', prove its totality, then use that to define a total version expand of expand'. From then on I will only use expand without referencing expand'. Is this bad practice?

import Mathlib

def PSeq : Type := List 

def bad_root (s : PSeq) : Option (Fin (s.length)) :=
  match s with
  | [] => none
  | x :: s' =>
    (x :: s').findFinIdx? (· < x)

def good_part (s : PSeq) : Option PSeq :=
  match bad_root s with
  | some br => some (s.take br)
  | none => none

-- First define expansion, then prove it total

def expand' (s : PSeq) : Option PSeq :=
  if (bad_root s).isSome
    then good_part s
    else s

lemma expand'_total (s : PSeq) : (expand' s).isSome := by {
  simp [expand']
  split
  simp [good_part]
  split
  · trivial
  rename (bad_root s).isSome = true => h2
  rename bad_root s = none => h3
  rw [ h2]
  rw [h3]
  trivial
  trivial
}

def expand (s : PSeq) : PSeq :=
  (expand' s).get (expand'_total s)

-- From here on, expand' will never be used, only expand will.

Kenny Lau (Aug 18 2025 at 09:35):

as long as you have good API, you can do anything you want

Eric Wieser (Aug 18 2025 at 12:45):

Though in this case you enumerate the list twice rather than once, which matters if you #eval


Last updated: Dec 20 2025 at 21:32 UTC