doc(RabinCertificate): correct the _of_card rationale and signature - #307
Conversation
The `_of_card` wrappers added in #306 are correct, but their docstrings justified the numeral form by claiming the `Fintype.card F` form makes a from-empty kernel replay reduce `Fintype.card F` (for a `ZMod p` field, an enumeration of ~`p` elements). It does not: `rw [hcard]` elaborates to `Eq.mpr (id (congrArg motive hcard)) cert`, whose kernel check only beta-reduces the motive, so `Fintype.card F` never reaches whnf position. Measured kernel type-checking of both proofs is single-digit milliseconds either way, with run-to-run variance exceeding the difference between the forms; and since Lean kernel-checks each theorem at `addDecl` during an ordinary build, a from-empty replay runs that same check. Replace the rationale with the one that does hold, and that `irreducible_X_pow_four_sub_C_of_card` already documents on the binomial side: the generated certificates are already stated in terms of `fieldSize`, so each Rabin condition applies directly instead of needing a `rw [hcard]` cast. Also drop the claim that the two forms are "definitionally equal" — the plain form is the `q := Fintype.card F` instance of the numeral one. Make `q` implicit and rename `hq` to `hcard`, matching the binomial `_of_card` form: `q` is uniquely determined by `hcard`, which precedes `h_trace`/`h_cop`, so inference never needs higher-order matching. Update `docs/wiki/field-extensions.md`, whose "Adding a new non-binomial extension" recipe still routed new extensions to the non-`_of_card` wrappers that the two canonical callers had moved away from, per the maintenance contract in `docs/wiki/README.md`. Pin the round trip in `CompPolyTests.RabinCertificate`: instantiating each `_of_card` form at `q := Fintype.card F` with `rfl` must recover the plain statement verbatim, so "nothing is weakened" is checked rather than asserted. The opposite direction is the wrapper's own proof body. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
🤖 PR SummaryThis PR corrects the documentation and API signature of the No Documentation
Refactoring
Testing
Statistics
Lean Declarations ✏️ Added: 2 declaration(s)
📋 **Additional Analysis**The diff conforms to the project's PR guidelines and style conventions. All naming, naming logic, module layout, variable conventions, and deprecation policy are respected. The description and title are formatted correctly, the 📄 **Per-File Summaries**
Last updated: 2026-08-18 00:35 UTC. |
Build Timing Report
Incremental Rebuild Signal
Slowest Current Build Files (warm library build)Showing 9 slowest current targets from the warm library build log, with comparison against the baseline warm library build log when available.
|
Follow-up to #306.
Motivation
The
_of_cardwrappers #306 added are correct and the KoalaBear proofs do read better for them, but two things were left inconsistent.The stated rationale does not hold. The docstrings justified the numeral form by claiming the
Fintype.card Fform forces a from-empty kernel replay to reduceFintype.card F— "for aZMod pfield, an enumeration of ~pelements". It does not.rw [hcard]elaborates toEq.mpr (id (congrArg motive hcard)) cert, whose kernel check only beta-reduces the motive, soFintype.card Fnever reaches whnf position. Measured kernel type-checking of both proofs, three runs each:rw [hcard]_of_cardrw [hcard]_of_cardRun-to-run variance within a single form exceeds the difference between the forms. And since Lean kernel-checks every theorem at
addDeclduring an ordinarylake build, a from-empty replay runs that same check — had the previous form forced a 2^31-element enumeration,maincould not have built.The real benefit is the one
irreducible_X_pow_four_sub_C_of_cardalready documents on the binomial side: the generated certificates are already stated in terms offieldSize(chainExp 1 steps = fieldSize ^ d), so each Rabin condition applies directly instead of needing arw [hcard]cast. The docstrings now say that.The wiki still pointed at the old wrappers. Step 3 of "Adding a new non-binomial extension" in
docs/wiki/field-extensions.md— the recipe every new extension follows — namedirreducible_of_rabin_prime_degree/irreducible_of_rabin_degree_six, while the two canonical callers had moved to the_of_cardforms. So the repo was giving two conflicting instructions about which wrapper to use. Per the maintenance contract indocs/wiki/README.md.Changes
RabinCertificate.lean— rewrite both_of_carddocstrings with the accurate rationale; drop "the two forms are definitionally equal" (the plain form is theq := Fintype.card Finstance of the numeral one, not a defeq variant); add an### Explicit-cardinality formssection header, since the new declarations sat under a header whose prose described only the twoFintype.card-shaped wrappers; mention the forms in the module docstring.qimplicit ({d q : ℕ}) and renamehqtohcard, matchingirreducible_X_pow_four_sub_C_of_card.qis uniquely determined byhcard, which precedesh_trace/h_cop, so inference never needs higher-order matching againstX ^ (?q ^ d). Both call sites shorten; the quintic one returns to a single line.QuinticIrreducible.lean— the module docstring still named the pre-feat: make KoalaBear Rabin irreducibility certificates re-checkable by kernel replay #306 lemma.docs/wiki/field-extensions.md— name the_of_cardforms in the API table, the wrapper table, and the recipe; note that a compositedwith no_of_cardform still usesirreducible_of_rabin_two_prime_factorswith arw [hcard]cast.tests/CompPolyTests/Data/Polynomial/RabinCertificate.lean— pin the round trip.prime_degree_recovered/degree_six_recoveredinstantiate each_of_cardform atq := Fintype.card Fwithrfland must yield the plain statement verbatim, so "nothing is weakened" is CI-enforced rather than asserted, and a future edit cannot silently add a hypothesis or shift an exponent. The opposite direction is the wrapper's own proof body.No statement changes:
quinticPoly_irreducible,sexticPoly_irreducibleand bothFactinstances are untouched.Validation
lake build(2631 jobs),lake test,./scripts/lint-style.sh,python3 ./scripts/check-docs-integrity.py— all clean. Axiom hygiene of both irreducibility theorems re-checked:[propext, Classical.choice, Quot.sound].Note for maintainers unrelated to this diff:
scripts/lint-style.shglobs onlyCompPoly/**/*.leanand*.lean, sotests/is never linted. I ranlint-style.pyon the changed test file separately (clean), but the gap is worth closing.🤖 Generated with Claude Code