Skip to content

feat(FreeWP): weakest preconditions for FreeM via Std.Do#62

Open
tannerduve wants to merge 7 commits into
Shreyas4991:mainfrom
tannerduve:feat/wp-free
Open

feat(FreeWP): weakest preconditions for FreeM via Std.Do#62
tannerduve wants to merge 7 commits into
Shreyas4991:mainfrom
tannerduve:feat/wp-free

Conversation

@tannerduve
Copy link
Copy Markdown
Contributor

@tannerduve tannerduve commented Jun 2, 2026

Port of cslib 604: logical handlers (LHandler) into PredTrans, wpH as the unique monad morphism from FreeM, adequacy theorem, HasHandler instances plugging FreeM into Std.Do's WP/WPMonad/Triple infrastructure, plus state/reader handlers with @[spec] lemmas and tests.

Follows Vistrup, Sammler, Jung. Program Logics a la Carte. POPL 2025.

Port of cslib feat/free-logic: logical handlers (LHandler) into PredTrans,
wpH as the unique monad morphism from FreeM, adequacy theorem, HasHandler
instances plugging FreeM into Std.Do's WP/WPMonad/Triple infrastructure,
plus state/reader handlers with @[spec] lemmas and tests.

Follows Vistrup, Sammler, Jung. Program Logics a la Carte. POPL 2025.
…lMonad

Restate wpH_pure/wpH_liftBind/wpH_bind on the FreeM constructor forms that
Cslib's simp set normalizes to, un-simp wpH_lift (mirroring liftM_lift), and
remove the LawfulMonad instance unused by the adequacy proof.
Connect the FreeM weakest-precondition framework to the repo's query
model (Prog Q α := FreeM Q α): derive a logical handler from a
Model Q Cost via evalQuery, register it for ReadOnlyVec, and prove an
adequacy theorem plus mvcgen-discharged Hoare triples over query
programs.
Comment thread AlgoleanTests/FreeMonadWP.lean
Move the weakest-precondition bridge out of the test file and generalize it
in QueryModel.lean: `Model.handler`, a `HasModel` class with a single generic
`HasHandler` instance, the `Spec.query` rule, adequacy (`Model.wp_eq_wp_interp`),
and `eval_of_triple`. Register `HasModel` for `ReadOnlyVec`/`Vec`. The handler
reasons about the result value only (`.pure`), so it needs no algebra on `Cost`.

Add Algolean/Algorithms/VecBubbleSort.lean: bubble sort in `Prog (Vec α)` using
read/write, proved fully correct via `mvcgen` (`bubbleSort_perm`,
`bubbleSort_sorted`). Split into `bubblePass` + `bubbleSort`, each a single-loop
mvcgen proof composed through `bubblePass_spec` — the worked non-trivial mvcgen
example for the query model. Slim FreeMonadWP.lean down to the ReadOnlyVec
examples using the generalized infra.
…before section

Address review: replace the explicit totality/transitivity hypotheses on the
public `bubblePass_spec`/`bubbleSort_spec`/`bubbleSort_perm`/`bubbleSort_sorted`
with `[Std.Total (fun a b => le a b = true)]` / `[IsTrans α (fun a b => le a b = true)]`,
matching `mergeSort`/`insertionSort`. The `∀`-form facts are derived once inside
`bubblePass_spec` for the (private, grind-friendly) pointwise helpers.

Also move `@[expose] public section` to after the module docstring.
Copy link
Copy Markdown
Owner

@Shreyas4991 Shreyas4991 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically omega is not the best way to do nat arithmetic. grind or lia are the preferred alternatives. I have managed to highlight only some of them.

Also I think there are some haves that can be inlined.

Comment thread Algolean/Algorithms/VecBubbleSort.lean Outdated
Comment thread Algolean/Algorithms/VecBubbleSort.lean Outdated
Comment thread Algolean/Algorithms/VecBubbleSort.lean Outdated
Comment thread Algolean/Algorithms/VecBubbleSort.lean Outdated
Comment thread Algolean/Algorithms/VecBubbleSort.lean Outdated
Comment thread Algolean/Algorithms/VecBubbleSort.lean Outdated
Comment thread Algolean/Algorithms/VecBubbleSort.lean Outdated
Address review:
- Replace `omega` with `lia` for the Nat-arithmetic side goals (the `grind`
  calls that need `Fin.val_mk` reduction are left as `grind`).
- Remove the `htot`/`htr`/`hrefl` `have`s from `bubblePass_spec`: the private
  pointwise helpers (`maxAt_swap`/`maxAt_noswap`/`maxAt_zero`) now take the
  `[Std.Total]`/`[IsTrans]` instances directly and materialize the facts they
  need locally, so the spec just lets the instances flow through.
Drop the `htot`/`htr`/`hrefl` `have` aliases entirely. The private pointwise
helpers take the order facts as plain arguments (so `grind` reads them as local
hypotheses — it can't consume a typeclass instance directly), and `bubblePass_spec`
passes the terms inline: `Std.Total.total` / `IsTrans.trans` resolve the relation
from each argument's expected type, and `Std.Refl.refl` (free from the Total→Refl
instance) supplies reflexivity. The public theorems keep their `[Std.Total]` /
`[IsTrans]` instances.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants