lean4-htt/tests/lean/run/partial_fixpoint_explicit.lean
Joachim Breitner 7b813d4f5d
feat: partial_fixpoint: partial functions with equations (#6355)
This PR adds the ability to define possibly non-terminating functions
and still be able to reason about them equationally, as long as they are
tail-recursive or monadic.

Typical uses of this feature are
```lean4
def ack : (n m : Nat) → Option Nat
  | 0,   y   => some (y+1)
  | x+1, 0   => ack x 1
  | x+1, y+1 => do ack x (← ack (x+1) y)
partial_fixpiont

def whileSome (f : α → Option α) (x : α) : α :=
  match f x with
  | none => x
  | some x' => whileSome f x'
partial_fixpiont

def computeLfp {α : Type u} [DecidableEq α] (f : α → α) (x : α) : α :=
  let next := f x
  if x ≠ next then
    computeLfp f next
  else
    x
partial_fixpiont

noncomputable def geom : Distr Nat := do
  let head ← coin
  if head then
    return 0
  else
    let n ← geom
    return (n + 1)
partial_fixpiont
```

This PR contains

* The necessary fragment of domain theory, up to (a variant of)
Knaster–Tarski theorem (merged as
https://github.com/leanprover/lean4/pull/6477)
* A tactic to solve monotonicity goals compositionally (a bit like
mathlib’s `fun_prop`) (merged as
https://github.com/leanprover/lean4/pull/6506)
* An attribute to extend that tactic (merged as
https://github.com/leanprover/lean4/pull/6506)
* A “derecursifier” that uses that machinery to define recursive
function, including support for dependent functions and mutual
recursion.
* Fixed-point induction principles (technical, tedious to use)
* For `Option`-valued functions: Partial correctness induction theorems
that hide all the domain theory

This is heavily inspired by [Isabelle’s `partial_function`
command](https://isabelle.in.tum.de/doc/codegen.pdf).
2025-01-21 09:54:30 +00:00

64 lines
1.5 KiB
Text

/-!
Tests for `partial_fixpoint` with explicit proofs
-/
/-- warning: declaration uses 'sorry' -/
#guard_msgs in
def nullary (x : Nat) : Option Unit := nullary (x + 1)
partial_fixpoint monotonicity sorry
-- Check for metavariables
set_option pp.mvars.anonymous false in
/--
error: don't know how to synthesize placeholder for argument 'a'
context:
⊢ Lean.Order.monotone fun f x => f (x + 1)
-/
#guard_msgs in
def nullarya (x : Nat) : Option Unit := nullarya (x + 1)
partial_fixpoint monotonicity id _
def nullaryb (x : Nat) : Option Unit := nullaryb (x + 1)
partial_fixpoint monotonicity fun _ _ a _ => a _
/-- info: nullaryb.eq_1 (x : Nat) : nullaryb x = nullaryb (x + 1) -/
#guard_msgs in #check nullaryb.eq_1
-- Type error
/--
error: type mismatch
()
has type
Unit : Type
but is expected to have type
Lean.Order.monotone fun f x => f (x + 1) : Prop
-/
#guard_msgs in
def nullary2 (x : Nat) : Option Unit := nullary2 (x + 1)
partial_fixpoint monotonicity ()
-- Good indent (bad indents are tested in partial_fixpoint_parseerrors
def nullary4 (x : Nat) : Option Unit := nullary4 (x + 1)
partial_fixpoint monotonicity
fun _ _ a x => a (x + 1)
-- Tactics
/-- info: Try this: exact fun x y a x => a (x + 1) -/
#guard_msgs in
def nullary6 (x : Nat) : Option Unit := nullary6 (x + 1)
partial_fixpoint monotonicity by
exact?
#guard_msgs in
def nullary7 (x : Nat) : Option Unit := nullary7 (x + 1)
partial_fixpoint monotonicity by
apply Lean.Order.monotone_of_monotone_apply
intro y
apply Lean.Order.monotone_apply
apply Lean.Order.monotone_id