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).
36 lines
893 B
Text
36 lines
893 B
Text
axiom A : Type
|
||
axiom B : Type
|
||
|
||
axiom A.toB : A → B
|
||
axiom B.toA : B → A
|
||
|
||
open Lean.Order
|
||
|
||
instance : PartialOrder A := sorry
|
||
-- It’s 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
|