Factor the suite's generators into a monad-polymorphic Generable class - #24
Merged
Merged
Conversation
Each shape the suite generates had a generator written specifically at `Plausible.Gen` (a `genXWith` per wrapper), even though the underlying `genX` combinators are already polymorphic in Basalt's `Gen`. Factor each into one interpretation-polymorphic `genXG`, add a `Generable` class naming the canonical generator per type, and derive every `Arbitrary` instance from it — calling `genXG` at `Plausible.Gen` with the existing `Gen.sized`/`retryGen` wrapping, so the draws are byte-for-byte unchanged and `lake test` behaves identically. Retry is now explicitly a per-interpretation harness concern rather than part of the generator: `genLExpr`'s `retryCont` (and the inner `retryGen` of the procedure/program generators) default to `id` in the canonical generator; the Plausible `Arbitrary` passes `retryGen`/`retryGenArg` on top. Covers all twelve wrapper types (expressions, commands, functions, statements, procedures, programs, ADT / independent blocks). Doc references to the removed `genXWith` helpers are updated. No new dependency beyond Basalt's `Gen` class and no behavior change to the Plausible suite; the registry's generators can now run under any `Gen` interpretation. Confirmed draw-for-draw identical to the original: because `Plausible.Gen` is a pure `StateT (ULift StdGen) (ReaderT (ULift Nat) (Except GenError))`, each `Arbitrary` can be run with an explicit `mkStdGen seed` and no global RNG. Dumping all twelve instances across a grid of seeds and sizes before and after the refactor produced byte-identical output (matching sha256).
ngernest
approved these changes
Sep 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The purpose of this change is to prepare for use of different
Basalt.Genbackends (including one backed by coverage-guided fuzzing), not justPlausible.Gen.Description of changes:
Each shape the suite generates had a generator written specifically at
Plausible.Gen(agenXWithper wrapper), even though the underlyinggenXcombinators are already polymorphic in Basalt'sGen. Factor each into one interpretation-polymorphicgenXG, add aGenerableclass naming the canonical generator per type, and derive everyArbitraryinstance from it — callinggenXGatPlausible.Genwith the existingGen.sized/retryGenwrapping, so the draws are byte-for-byte unchanged andlake testbehaves identically.Retry is now explicitly a per-interpretation harness concern rather than part of the generator:
genLExpr'sretryCont(and the innerretryGenof the procedure/program generators) default toidin the canonical generator; the PlausibleArbitrarypassesretryGen/retryGenArgon top.Covers all twelve wrapper types (expressions, commands, functions, statements, procedures, programs, ADT / independent blocks). Doc references to the removed
genXWithhelpers are updated. No new dependency beyond Basalt'sGenclass and no behavior change to the Plausible suite; the registry's generators can now run under anyGeninterpretation.Confirmed draw-for-draw identical to the original: because
Plausible.Genis a pureStateT (ULift StdGen) (ReaderT (ULift Nat) (Except GenError)), eachArbitrarycan be run with an explicitmkStdGen seedand no global RNG. Dumping all twelve instances across a grid of seeds and sizes before and after the refactor produced byte-identical output (matching sha256).By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.