Skip to content

Documentation refresh for monad transformers - #4724

Merged
satorg merged 8 commits into
typelevel:mainfrom
reardonj:documentation-refresh-monad-transformers
Oct 31, 2026
Merged

satorg merged 8 commits into
typelevel:mainfrom
reardonj:documentation-refresh-monad-transformers

Conversation

@reardonj

@reardonj reardonj commented Mar 4, 2025

Copy link
Copy Markdown
Contributor

This PR came out of a discussion in the Typelevel discord with @djspiewak and @armanbilge regarding unexpected interactions with monad transformers and Cats Effect.

This PR moves around monad transformer documentation to better reflect that it is a more advanced topic:

  • updates the monad transformer documentation
    • to move the overview to a separate section instead of the jump start guide
    • change uses of Future to Try to avoid suggesting developers use the deprecated Future instances
    • add a Pitfalls section to warn users about unfortunate interactions with CE and direct users to Cats MTL as an alternative.
  • moves the Monad Transformer documentation pages out of Data Types to their own section.

I also made a few related changes for consistency:

  • remove the pointless Datatypes index pages that just listed all the datatype page links
  • move the Typeclass page to and Overview page under the Typeclasses section.
  • fix a broken link in guidelines.md

image
image

@valencik valencik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

NICE!!! 🎉
Thanks so much for putting in this effort, I'm really excited about it.

I think this is a good organizational change, I like the reduced Future usage, and less transformers in the return types.
I think we can go a little bit further calling out the pitfalls. Namely, let's repeat them on their respective transformer pages.
And let's call out the return types advice more prominently.


`Either` can be used for error handling in most situations. However, when
`Either` is placed into effectful types such as `Option` or`Future`, a large
`Either` is placed into effectful types such as `Option`, a large

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There's still an example using Future below this, but I think if we change that it should happen in another PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ya. Examples are awkward since one of the big motivations is IO, but we can't depend on CE here.

Comment thread docs/monadtransformers/index.md Resolved
Comment thread docs/monadtransformers/index.md Outdated
The above `map` will return a value of type `OptionT[Try, String]`.

To get the underlying `Try[Option[String]]` value, simply call `.value` on the `OptionT` instance.
In practice, you should not include monad transformers in function signatures, and only use them as locally-scoped utilities to reduce boilerplate so that calling code is not required to care about the composition.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This sentence is kind of buried here, but I think it was a key point of the recent discussion about transformers.
Can we perhaps highlight this in a section of its own?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

image

class Account { /* ... */ }
class Money { /* ... */ }

def findUserById(userId: Long): Try[Option[User]] = { /* ... */ ??? }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just want to note that these have changed from
OptionT[Future, User] to Try[Option[User]]

I think this is a good improvement if we're trying to recommend that folks don't use transformers in return types.

Comment thread docs/monadtransformers/index.md Outdated
While powerful, this can lead to unwieldy type signatures and poor type inference.
The [Cats MTL](https://typelevel.org/cats-mtl/) project provides a capability based approach to extend effect types without requiring as much boilerplate.

Some monad transformers can also interact poorly with more powerful effect types that provide concurrent computation, such as Cats Effect's `IO` or fs2's `Stream`. You should avoid `StateT` and `WriterT` and use the concurrent data types provided by those libraries instead. Because `IO` already provides its own error channel, `EitherT[IO, Throwable]` can also lead to confusing behavior; prefer `IO`'s own error channel instead. No newline at end of file

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this warning should definitely be repeated on the EitherT, StateT, and WriterT, pages.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

image
image
image

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the screenshots.
I think these are good.
The warning on EitherT is a little too up top front and center, but I don't think that's a blocker.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I couldn't identify a nice place to put that one, EitherT doesn't have a convenient intro like the other ones.

Comment thread docs/monadtransformers/index.md Resolved
@reardonj
reardonj force-pushed the documentation-refresh-monad-transformers branch from 518bcd6 to 9264f63 Compare March 5, 2025 03:10
@valencik

valencik commented Mar 8, 2025

Copy link
Copy Markdown
Member

To minimize these pitfalls, monad transformers should only be used as locally-scoped utilities to reduce boilerplate.
Do not include monad transformers in public method signatures.
Calling code can always use monad transformers themselves.

@typelevel/cats Anyone strongly disagree with this advice?

This PR has a somewhat large diff, but the focus of it is calling out this often repeated advice (and less examples with Future, and calling out more gotchas).

@valencik

valencik commented Mar 8, 2025

Copy link
Copy Markdown
Member

I should perhaps note, "strongly disagree" isn't the only option 😆
Adding more nuance is totally good too!

@lenguyenthanh lenguyenthanh left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

some nit about using * import instead of _ import

Comment thread docs/imports.md Resolved
@reardonj

Copy link
Copy Markdown
Contributor Author

@valencik , I completely forgot this PR existed. Any chance we can get it merged?

@reardonj

Copy link
Copy Markdown
Contributor Author

Any @typelevel/cats maintainers able to review this? The subject came up again in ⁠Discord yesterday and it would be really nice to have documentation to point at.

djspiewak
djspiewak previously approved these changes Jul 29, 2026

@djspiewak djspiewak left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm on the fence because this is definitely an improvement over what's there, but it stops short of a more full rewrite (understandably!) and so the effect is kind of mixed. We still have holdover phrases like "in production, you'll often use such and such" when in reality people shouldn't be using this stuff in production 99% of the time.

@reardonj

Copy link
Copy Markdown
Contributor Author

We still have holdover phrases like "in production, you'll often use such and such" when in reality people shouldn't be using this stuff in production 99% of the time.

…ya, I didn't want to get into the argument of whether people should even use this stuff. But just taking it out of the getting started guide will hopefully help there.

Comment thread docs/datatypes/directory.conf Resolved
Comment thread docs/datatypes.md Resolved
Comment thread docs/typeclasses/index.md Resolved
Comment thread docs/monadtransformers/optiont.md Resolved
@satorg

satorg commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

@reardonj , one note (perhaps, out of the scope of this PR, but it's still worth mentioning): with these changes both sub-directories docs/typeclasses and docs/monadtransformers get an index.md (which is rendered as "Overview"), but docs/datatypes doesn't get any which makes it looking like an outsider.

Comment thread docs/monadtransformers/eithert.md Resolved
Comment thread docs/monadtransformers/index.md Resolved
Comment thread docs/monadtransformers/index.md Resolved
Comment thread docs/typeclasses/lawtesting.md Resolved
@satorg

satorg commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

@reardonj , thank you for the PR! Would you mind its branch it to the current main please (either by merging or rebasing – your choice). Thank you!

@satorg
satorg requested a review from lenguyenthanh October 26, 2026 06:45
reardonj and others added 4 commits October 26, 2026 08:34
- add warnings to specific transformer pages
- call out recommended usage more specifically
- add CE link
- fix broken links
- add a small overview page for data types
- fix number of type parameters for EitherT
@reardonj
reardonj force-pushed the documentation-refresh-monad-transformers branch from b8a8984 to 344d6ed Compare October 26, 2026 12:37
@reardonj

Copy link
Copy Markdown
Contributor Author

@satorg , I think I have addressed all the comments. I did a clean rebase. I have also added a very small overview page for datatypes so we have something to link to.

Comment thread docs/jump_start_guide.md
Otherwise, if the result of all three calls contains `Some`, the final outcome will also contain `Some`.


## EitherT

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@reardonj , it looks like while the OptionT section above was moved (with some tweaks) to docs/monadtransformers/index.md, however this EitherT one was dropped entirely.

Is that correct? Was it intentional or just occasionally missed out?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

At this point, I can't say I recall what my intent was. I suspect it was that OptionT was a sufficient example for the monad transformers intro, and the EitherT stuff in the jump-start guide was covering the same territory as the actual EitherT doc.

Looking over that old content again, I see the EitherT doc is missing some sections (right bias, OptionT transforms). I've pulled that in.

Comment thread docs/monadtransformers/index.md Resolved
- Include part of the section on right bias
- Include section on OptionT -> EitherT
- move .value section up higher
- fix mdoc errors
- group tranforming sections to simplify titles
@reardonj

Copy link
Copy Markdown
Contributor Author

Also made a few tweaks to the EitherT docs in general so the sections titles are more readable:

image

@reardonj
reardonj requested a review from satorg October 27, 2026 12:34

@satorg satorg left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM, thank you!

@satorg
satorg merged commit e28985f into typelevel:main Oct 31, 2026
16 checks passed
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.

5 participants