lean4-htt/tests/lean/run/partial_fixpoint_mutual.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

36 lines
893 B
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

axiom A : Type
axiom B : Type
axiom A.toB : A → B
axiom B.toA : B → A
open Lean.Order
instance : PartialOrder A := sorry
-- Its important that the CCPO instance isn't completely axiomatic, so that
-- `instCCPO.toOrder` is defeq to `instOrder`
instance : CCPO A where
csup := sorry
csup_spec := sorry
instance : PartialOrder B := sorry
instance : CCPO B where
csup := sorry
csup_spec := sorry
@[partial_fixpoint_monotone] axiom monotone_toA :
∀ {α} [PartialOrder α] (f : α → B), monotone f → monotone (fun x => B.toA (f x))
@[partial_fixpoint_monotone] axiom monotone_toB :
∀ {α} [PartialOrder α] (f : α → A), monotone f → monotone (fun x => A.toB (f x))
mutual
noncomputable def f : A := g.toA
partial_fixpoint
noncomputable def g : B := f.toB
partial_fixpoint
end
/--
info: equations:
theorem f.eq_1 : f = g.toA
-/
#guard_msgs in #print equations f