Zulip Chat Archive
Stream: mathlib4
Topic: Writer should use an additive monoid
Shreyas Srinivas (Feb 20 2026 at 17:02):
Hi all, Thanks to some downstream discussions in #CSLib I discovered that mathlib's WriterT uses a Monoid instance on its log type. I have made a PR to fix this to AddMonoid. Here is the PR : mathlib4#35578
Arguments in favour of this change:
- This is the actual intended meaning of the Writer monad. Haskell uses
Monoidbecause it makes no distinction betweenAddMonoidandMonoid. The writer monad is supposed to act like a log. So for instance it might be collecting a list of log-records, the natural writer monad operation is to concatenate to this list, not take element-wise pairs. It might be counting events, in which case the count needs to be increased additively. - This change only affects one other file in mathlib, the
ContTmonad, which I have naturally fixed in the PR. - It would be super useful in cslib#275 to handle cost functions as well as replace the so-called
Timemonad which is just a writer monad in disguise.
Shreyas Srinivas (Feb 20 2026 at 17:02):
CC : @Eric Wieser
Shreyas Srinivas (Feb 20 2026 at 17:14):
I'd be very grateful if we could reach a fast consensus on this, since it would potentially help us kickstart formalizing algorithms in cslib soon.
Eric Wieser (Feb 20 2026 at 17:36):
Relatedly I wonder if we should remove the duplication for EmptyCollection/Zero, and force users who want to use List X as their log type to use Free(Add)Monoid X instead
Eric Wieser (Feb 20 2026 at 17:37):
the natural writer monad operation is to concatenate to this list, not take element-wise pairs
Neither * nor + mean concatenate in Lean, so this argument doesn't seem to favor either Monoid or AddMonoid. Unless of course you use Free(Add)Monoid, and then both mean concatenate!
Shreyas Srinivas (Feb 20 2026 at 17:38):
Yeah, but morally it is an addition operation. The choice of notation ++ is close enough
Eric Wieser (Feb 20 2026 at 17:38):
The best argument I can see to prefer Monoid is that the log concatenation is typically non-commutative, and in mathematics we prefer to use * instead of + when the operation is non-commutative.
Shreyas Srinivas (Feb 20 2026 at 17:39):
Yes, but as I pointed out in the PR comment, we actually have a separate class for that AddCommMonoid, which indicates that non-commutative uses of + have already been anticipated
Eric Wieser (Feb 20 2026 at 17:40):
But I do see the appeal in using + for convenience for CSLib, and in the absence of any other users it seems harmless enough to change it.
Eric Wieser (Feb 20 2026 at 18:14):
A perhaps more conservative approach would be to define AddWriterT and use to_additive to manage the duplication
Shreyas Srinivas (Feb 20 2026 at 18:56):
Given that writer is currently hardly used anywhere is Mathlib, I think we should let the default writer be additive and create a MulWriter if necessary
Christian Merten (Feb 20 2026 at 19:01):
https://ncatlab.org/nlab/show/action+monad uses multiplicative monoids in the first part and switches to additive notation in section 5 when discussing the "logging-effect in computer science".
Snir Broshi (Feb 20 2026 at 19:50):
Shreyas Srinivas said:
- It would be super useful in cslib#275 to handle cost functions as well as replace the so-called
Timemonad which is just a writer monad in disguise.
I don't know the details about either monad, but can't CSLib do TimeM := WriterT <| Multiplicative ℕ? (or TimeM := WriterT <| Multiplicative T after Eric's latest change)
Shreyas Srinivas (Feb 20 2026 at 20:01):
It’s tedious and and tbh writer monads have a default meaning in CS. They w is additive.
Snir Broshi (Feb 20 2026 at 20:10):
What, how is a single line more tedious than a monad definition from scratch?
Shreyas Srinivas (Feb 20 2026 at 20:19):
Every monoid property or theorm has to be applied with toMultiplicative
Shreyas Srinivas (Feb 20 2026 at 20:20):
And as I point out the moral definition is additive. The change is not huge. This monad is not even being used in mathlib beyond the Cont monad
Shreyas Srinivas (Feb 20 2026 at 20:21):
I honestly don’t even see why this is controversial. Even ncatlab prefers the name Action monad for the multiplicative version.
Shreyas Srinivas (Feb 20 2026 at 20:23):
Even the documentation for this module refers to the Haskell definition and there the primary usage is definitely with additive operations.
Snir Broshi (Feb 20 2026 at 21:27):
Shreyas Srinivas said:
I honestly don’t even see why this is controversial
To be clear: I do not have an opinion on the Mathlib change, I suggested a way to unblock CSLib
Shreyas Srinivas (Feb 20 2026 at 22:03):
I think merging this PR soon would be a great help in simplifying CSLib. It seems to be practically a neglected leaf node as far as mathlib goes.
Jovan Gerbscheid (Feb 20 2026 at 23:53):
Why don't we just move the WriterT definition to CSLib altogether, and let them do with it what they want? To me the writer monad seems hardly useful when you can use a state monad instead.
Shreyas Srinivas (Feb 20 2026 at 23:55):
@Eric Wieser : given the sparse API for writer I am inclined to take this option as a practical route but with a change: I’ll copy WriterT as AddWriterT into a CSLib for now.
Shreyas Srinivas (Feb 21 2026 at 00:00):
Fwiw I think writerT should still be fixed here and StateT is not a replacement for WriterT. However I need to make progress faster than we can reach consensus here.
Shreyas Srinivas (Feb 21 2026 at 00:00):
I view this "port" as a stopgap
Eric Wieser (Feb 21 2026 at 00:13):
I’ll copy WriterT as AddWriterT into a CSLib for now.
I'd be inclined to keep it as TimeM until we need the generality
Shreyas Srinivas (Feb 21 2026 at 00:14):
I am really keen to avoid the TimeM dependency. Anyway, an additive writer monad is essential CS material. We can have something in Cslib until mathlib's slow process catches up
Eric Wieser (Feb 21 2026 at 00:18):
Shreyas Srinivas said:
Anyway, an additive writer monad is essential CS material
According to haskell, only the ++/empty version is CS material. I'm not sure where the "CS is +, Math is *" divide is coming from here.
Shreyas Srinivas (Feb 21 2026 at 00:21):
I am referring to this ncatlab entry on the action monad which Christian cited
Shreyas Srinivas (Feb 21 2026 at 00:22):
That seems to be some pure math stuff
Shreyas Srinivas (Feb 21 2026 at 00:22):
https://github.com/leanprover/cslib/pull/360
Shreyas Srinivas (Feb 21 2026 at 00:50):
Christian Merten said:
https://ncatlab.org/nlab/show/action+monad uses multiplicative monoids in the first part and switches to additive notation in section 5 when discussing the "logging-effect in computer science".
See this
Shreyas Srinivas (Feb 21 2026 at 00:52):
Anyway this thread should continue to be about WriterT being multiplicative by default, and whether it should be additive by default or whether there's some other way to allow both Monoid and AddMonoid versions.
Christian Merten (Feb 21 2026 at 01:00):
Eric Wieser said:
A perhaps more conservative approach would be to define
AddWriterTand useto_additiveto manage the duplication
This seems to be the best solution to me.
Chris Henson (Feb 21 2026 at 01:00):
Just seeing this thread, thanks for linking from the CSLib PR, Eric. From the discussion above, the to_additive approach seems nice in providing either choice. Regarding this comment:
Shreyas Srinivas said:
We can have something in Cslib until mathlib's slow process catches up
This feels a bit premature for a PR opened just today, and I don't want to leap to duplicating anything downstream. (I also think this could be communicated a bit more graciously)
Michael Rothgang (Feb 21 2026 at 06:57):
The discussion here could equally be described as deliberate (as opposed to slow). This is not about a week-long delay where this PR is completely unnoticed.
Shreyas Srinivas (Feb 21 2026 at 11:00):
Okay I accept that I have been hasty. Apologies. But I do think it helps to have some additive version of the writer monad while we discuss mathlib’s API
Shreyas Srinivas (Feb 21 2026 at 11:02):
Also @Michael Rothgang this is not just about the discussion here. A PR can take several weeks to reach the first page of the review queue
Michael Rothgang (Feb 21 2026 at 11:06):
Shreyas Srinivas said:
Also Michael Rothgang this is not just about the discussion here. A PR can take several weeks to reach the first page of the review queue
I know (and agree that faster reviews would be great - the mathlib initiative has already made perceptable inroads to me). That said, a lot of this comes down to "are there reviewers for this particular area". It doesn't make sense for e.g. me to review deep category theory or t-computability. Complaining about slow reviews is easy (and still justified to some extent), changing this is harder :-)
Chris Henson (Feb 21 2026 at 11:51):
Also it is not as if CSLib is immune to this, we just have the luxury of smaller scale for the time being. The areas where I am truly comfortable reviewing are lambda calculi metatheory and metaprogramming. Anything else is me mainly addressing technical issues and pushes at the limits of both my competency and time constraints. I've gratefully accepted help from Eric and others in areas that are on the border between Mathlib and CSLib, and we will have our own growing pains of bootstrapping the expansion of CSLib reviewers/maintainers.
Shreyas Srinivas (Feb 21 2026 at 16:40):
Accepted. For what it’s worth, I found that the docstring linter is stricter in CSLib than mathlib. Is this something that is expected?
Chris Henson (Feb 21 2026 at 17:34):
Shreyas Srinivas said:
Accepted. For what it’s worth, I found that the docstring linter is stricter in CSLib than mathlib. Is this something that is expected?
I don't have permission to move messages from here, but we should take discussion to the CSLib channel to keep on topic. But to answer your question, you mean the docBlameenvironment linter? We inherit this from batteries, so it should work the same.
Jovan Gerbscheid (Feb 21 2026 at 17:45):
Maybe you are talking about the set_option linter.missingDocs true linter? This one is off in mathlib, and on in batteries. This is the syntax linter, not the environment linter. I wonder why there is this discrepancy between mathlib and batteries.
Shreyas Srinivas (Feb 21 2026 at 17:47):
No idea, but mathlib’s WriterT passes all linters clearly while in cslib#360, I had to add more docstrings. They are nearly identical.
Michael Rothgang (Feb 21 2026 at 17:54):
What kind of linter errors did you get? Yellow squiggles as you were writing code, or errors when typing #lint/in the "lint cslib" step of CI? (If the later, it's an environment linter.)
Shreyas Srinivas (Feb 21 2026 at 17:54):
lake lint
Shreyas Srinivas (Feb 21 2026 at 17:55):
And CI
Michael Rothgang (Feb 21 2026 at 17:55):
lake lint AFAICT does lake exe runLinter, which runs environment linters.
Chris Henson (Feb 21 2026 at 18:51):
In CSLib we have lintDriver = "batteries/runLinter" in our lakefile, while in Mathlib lake exe runLinter is run in CI. Is there some difference?
Chris Henson (Feb 21 2026 at 18:54):
Oh, Mathlib's scripts/nolints.json has several docBlame exceptions for WriterT, pretty sure that's it.
Last updated: Feb 28 2026 at 14:05 UTC