Skip to content

Fix parseRoutes brace-token comment, document TH-stage split requirement - #1926

Merged
jezen merged 1 commit into
yesodweb:masterfrom
jeongoon:feature/subsite-th-stage-docs
Jul 9, 2026
Merged

jezen merged 1 commit into
yesodweb:masterfrom
jeongoon:feature/subsite-th-stage-docs

Conversation

@jeongoon

@jeongoon jeongoon commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

What

  • Corrects an inaccurate comment in YesodCoreTest/ParameterizedSubDispatchRuntime.hs claiming that parseRoutes's {...} brace token only accepts single-token subsite types. It actually accepts any fully-applied type expression (e.g. {ParamSubsite ConcreteSub}), verified against Yesod.Routes.Parse.parseTypeTree.
  • Documents a previously-unstated GHC TH stage-restriction constraint in docs/split-route-compilation.md: splitting a subsite's Data module (mkYesodSubData) from its Dispatch module (mkYesodSubDispatch) into separately-compiled modules becomes mandatory — not just organizational — once a parameterized subsite mounts a different subsite as a leaf in its own route tree. Adds a matching Troubleshooting entry quoting the actual GHC error text.

Why

While working with parameterized subsites, I'd been declaring type synonyms just so {...} would have a single identifier to point at. Discovering that brace tokens actually accept any fully-applied type expression directly was a nice simplification — turns out a synonym is only needed when the target type can't be written as a bare applied expression (e.g. it involves a unit type like ()). Working through that also surfaced that the existing comment didn't reflect this, and that the related Data/Dispatch split requirement wasn't documented anywhere, even though yesod-core's own test suite already has a worked example of exactly this shape.

Testing

No code changes — comment and documentation only. Verified via stack build yesod-core (exit 0) that the touched files still compile cleanly.

Fixes an inaccurate comment claiming parseRoutes's `{...}` brace token
only accepts single-token subsite types; it actually accepts any
fully-applied type expression (verified against Yesod.Routes.Parse).
Documents a previously-unstated GHC TH stage-restriction constraint:
the Data/Dispatch module split becomes mandatory, not just
organizational, once a parameterized subsite mounts a different
subsite as a route-tree leaf.

Cycle decisions:
- Scope kept to comment/doc-only — no route/type changes
- Rewrote fixture comment explaining why ConcreteParamSub is now
  optional but ConcreteBigSub remains required
- Documented the split requirement in both the Recipe and
  Troubleshooting sections
- Written generically, with no reference to internal planning docs

Triage outcomes:
- F1 accepted (patched in-session by Claude) — corrected
  mkYesodSubDispatchInstance description (generates dispatch
  instances, not the datatype)
- F2 accepted (patched in-session by Claude) — added "route"
  qualifier to mkYesodSubData description
- F3 accepted (patched in-session by Claude) — Test plan updated to
  use sharness verify-test instead of bare stack build

Cycle: feature-subsite-th-stage-docs
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@jezen jezen 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.

This seems1 entirely AI generated, but that isn't to say it isn't still legit. I think some of the details here are kind of… irrelevant? Or at least not entirely useful to an actual human reading this. Though what's written here isn't necessarily final either; we can always refine this later.

What would make this contribution better (for other humans) would be a minimal concrete example of the pattern you're describing. Subsites in general are an under-documented (and important!) part of Yesod.

Footnotes

  1. Correct me if I'm wrong. ↩

@jezen
jezen merged commit 9e037d9 into yesodweb:master Jul 9, 2026
13 checks passed
@jeongoon

jeongoon commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

Hi @jezen — thanks again for reviewing this.

You noted this read as AI-generated (fair — I wrote it with Claude's help)
and asked for a minimal concrete example. Sorry it took a while to follow
up properly.

While working on that example, I found the docs I added here actually got
something wrong: the "When the subsite split is required, not optional"
section claims the split becomes required specifically when a
parameterized subsite mounts a different subsite. That's not the real
condition — it's required whenever mkYesodSubData's generated
resources* value is consumed by a later splice in the same module,
regardless of whether a child subsite is involved. I have a fix ready and
plan to open a follow-up PR for it — holding off on opening it until the
cookbook PR below is merged, so I can link the finished page directly
instead of a link that's still in review.

Digging further also turned up a second, previously-undocumented parser
limitation: when the mounted child subsite is itself generic (its type
depends on the parent's own type variable), the foundation-context string
parser can't parse the resulting constraints, and a type synonym doesn't
help the way it does for the {...}-brace case — a wrapper typeclass is
needed instead.

I originally hit this on my own site, jeongoon.space
(https://codeberg.org/myoungjin/jeongoon.space — very much a work in
progress, not a finished product), where a Story subsite (article writing)
mounts a generic, reusable list-management subsite underneath it. That code
was written against a pre-1.7 yesod-core, before mkYesodSubDispatchInstance
exposed a way to do this without hand-writing the dispatch instances — which
is a large part of why it went fully manual back then. I wrote the pattern
up as a yesod-cookbook page with a worked, compiling example (a comments
subsite reused across post/product types, backed by a real Persistent
query — a stand-in for the same shape, since it's easier to follow than my
actual article/list code), plus a companion page on the harder cases:
yesodweb/yesod-cookbook#54.

I'm naming the Claude-assisted authorship again on purpose — everything in
the cookbook pages is grounded in real usage on my own app, not
speculation, and I'd like it to hold up whether it's a human or another AI
reading it next.

@jezen

jezen commented Jul 13, 2026

Copy link
Copy Markdown
Member

This reads exactly like more Claude output.

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