Skip to content

feat(Data/PFunctor): add free monad of a polynomial functor#477

Open
quangvdao wants to merge 7 commits intoleanprover:mainfrom
quangvdao:quangvdao/pfunctor-freem
Open

feat(Data/PFunctor): add free monad of a polynomial functor#477
quangvdao wants to merge 7 commits intoleanprover:mainfrom
quangvdao:quangvdao/pfunctor-freem

Conversation

@quangvdao
Copy link
Copy Markdown

Summary

  • Port PFunctor.FreeM from VCV-io (ToMathlib/PFunctor/Free.lean) to cslib.
  • The free monad on a polynomial functor extends the W-type construction with an extra pure constructor, yielding a lawful monad that is free over P : PFunctor.

Main definitions

  • PFunctor.FreeM: inductive type with pure and roll constructors
  • FreeM.lift / FreeM.liftA: lifting from the base polynomial functor
  • Monad and LawfulMonad instances
  • FreeM.inductionOn / FreeM.construct: propositional and dependent eliminators
  • FreeM.mapM: canonical interpretation into any target monad, with simp lemmas for bind, map, seq, etc.

Notes

  • The MonadHom-related definitions (mapMHom, mapMHom') from the original VCV-io source are omitted since cslib does not have MonadHom infrastructure. These can be added later if cslib gains monad homomorphism support.
  • File placed at Cslib/Foundations/Data/PFunctor/FreeM.lean as a foundation for future polynomial functor work.
  • Builds cleanly with no linter warnings.

Posted by Cursor assistant (model: claude-4.6-opus-high-thinking) on behalf of the user (Quang Dao) with approval.

Made with Cursor

Port `PFunctor.FreeM` from VCV-io (ToMathlib/PFunctor/Free.lean).

This defines the free monad on a polynomial functor (`PFunctor`),
which extends the W-type construction with an extra `pure` constructor.

Main definitions:
- `PFunctor.FreeM`: inductive type with `pure` and `roll` constructors
- `FreeM.lift` / `FreeM.liftA`: lifting from the base functor
- `Monad` and `LawfulMonad` instances
- `FreeM.inductionOn` / `FreeM.construct`: elimination principles
- `FreeM.mapM`: canonical interpretation into any target monad

Made-with: Cursor
@quangvdao quangvdao force-pushed the quangvdao/pfunctor-freem branch from b713d7d to 2024bc5 Compare April 7, 2026 20:42
- Make `pure` constructor protected, add explicit `Pure`/`Bind`/`Functor`/`LawfulFunctor` instances
- Add `map`, `id_map`, `comp_map` as explicit definitions before typeclass wiring
- Replace `monad_pure_def`/`monad_bind_def` with `@[simp] pure_eq_pure`/`bind_eq_bind`
- Rename lemmas to subject-first form: `pure_bind`, `bind_pure`, `roll_bind`, `lift_bind`
- Add `bind_pure` (right identity) and `bind_pure_comp` lemmas
- Remove `@[always_inline, inline, reducible]` attributes from `lift`, `liftA`, `bind`
- Rename `mapM` parameter `s` to `interp`
- Add `mapM_seqLeft`, `mapM_seqRight` lemmas
- Update `mapM_lift` statement to simplified form

Made-with: Cursor
@eric-wieser
Copy link
Copy Markdown
Collaborator

Can you include an explanation of the difference with FreeM in the module docstring?

Rename the `roll` constructor and all associated lemma/parameter names
to `liftBind`, matching the naming convention of `Cslib.FreeM`.

Made-with: Cursor
Flip `pure_eq_pure` to normalize `FreeM.pure` to `pure` (typeclass),
matching the direction advocated in leanprover#417.

Adjust proofs of `bind_pure`, `bind_pure_comp`, `bind_eq_pure_iff`,
`pure_eq_bind_iff`, `pure_inj`, `mapM_bind`, and `mapM_map` to
account for the new simp normal form.

Made-with: Cursor
Add a "Comparison with Cslib.FreeM" section to the module docstring,
showing both liftBind constructors side by side and explaining that
PFunctor.FreeM avoids the universe bump from the existential in
Cslib.FreeM when the effect signature is naturally polynomial.

Made-with: Cursor
Both are redundant with the auto-generated FreeM.rec:
- construct is FreeM.rec restricted to Type* (strictly weaker)
- inductionOn is FreeM.rec restricted to Prop

Plain `induction x with | pure | liftBind` works out of the box.

Made-with: Cursor
Match the naming convention of Cslib.FreeM.liftM for the canonical
interpreter from the free monad into a target monad.

Made-with: Cursor
@quangvdao
Copy link
Copy Markdown
Author

Thanks @eric-wieser ! I believe I have addressed all of your comments, including the docstring explaining the difference with FreeM

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