Skip to content

Conversation

@adinapoli
Copy link
Contributor

Fixes #84 by implementing shrink for our existing Arbitrary instances via genericShrink.

As that requires the datatypes deriving a Generic instance, I have also added a genericsTool to smooth things out.

I have transplanted the dataTypeableTool that I used in Atlas to generate Data instances, for syb & co.

@adinapoli adinapoli requested a review from adamgundry October 28, 2025 15:02
Copy link
Contributor

@adamgundry adamgundry left a comment

Choose a reason for hiding this comment

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

Apologies for not realising before now, but I don't think we necessarily need to add tools that merely derive standard classes, because datatypesTool' already makes it possible to change the derived classes alongside the datatype definition. Maybe we need to make that API more convenient/discoverable, though.

I'm in two minds about use the use of genericShrink. I can see it is easy to add, but the additional compile-time cost seems like it could well be significant for a large schema, and it shouldn't be that hard (famous last words) to generate shrinker implementations using TH.

@adinapoli
Copy link
Contributor Author

Apologies for not realising before now, but I don't think we necessarily need to add tools that merely derive standard classes, because datatypesTool' already makes it possible to change the derived classes alongside the datatype definition. Maybe we need to make that API more convenient/discoverable, though.

@adamgundry yes, I'm aware of datatypesTool', but alas I can't remember now which specific problem (or self-inflicted problem) I stumbled upon when using it directly in Atlas, apologies for not coming up with a coherent narrative.

I'm in two minds about use the use of genericShrink. I can see it is easy to add, but the additional compile-time cost seems like it could well be significant for a large schema, and it shouldn't be that hard (famous last words) to generate shrinker implementations using TH.

I can try looking into that, or bail out if that proves to be too tricky; I understand that the compile-time cost for Generic on a big schema might be significant.

@adinapoli adinapoli force-pushed the adinapoli/issue-84 branch 3 times, most recently from f45a2e5 to ee08f85 Compare November 4, 2025 14:52
@adinapoli
Copy link
Contributor Author

@adamgundry I'm completely fried after a day intermittently staring at TH splices,but I think we are almost there, but I have ran out of steam on shrinkRecord, which works but it's not correct. I have mimicked the behaviour of what the generic instance would do, and the latter would generate something in this flavour:

    -- For records, using the same principle behind 'genericShrink', we need
    -- to generate a list of lists, each sublist being the shrinking of a single
    -- individual field, and finally mconcat everything together.
    -- Example:
    -- shrink = \(Foo a b c) ->
    --  (Foo <$> shrink a <*> pure b   <*> pure c) ++
    --  (Foo <$> pure   a <*> shrink b <*> pure c) ++
    --  (Foo <$> pure   a <*> pure b   <*> shrink c)

However, my TH-fu failed me and at the moment I'm generating something like:

Foo <$> shrink a <*> shrink b <*> shrink c

which wouldn't shrink properly, and I know for a fact as in the past (scrapped in the last commit) I have generated a QuickCheck property to check in lockstep the genericShrink behaviour. I think it would be relatively easy for you to fix my code.

Then, we can try in Atlas, maybe generating (locall) a silly test with a degenerate FK, and see if things shrinks fine (or, failing that, I can use my WIP traversal branch to generate a huge payload there).

@adinapoli adinapoli requested a review from adamgundry November 4, 2025 15:30
@adinapoli
Copy link
Contributor Author

@adamgundry This is now ready to go -- I have cherry-picked your commit and implemented shrinkEnum. Tested on Atlas that this is shrinking things as it should!

@adinapoli adinapoli force-pushed the adinapoli/issue-84 branch 2 times, most recently from c08c3c3 to 655aad0 Compare November 5, 2025 13:55
adinapoli and others added 4 commits November 5, 2025 15:26
Implement:

* `shrinkNewtype` to shrink `SpecNewType`;
* `shrinkUnion`   to shrink `SpecUnion`;
* `SpecEnum` does not shrink;
* `shrinkRecord`  to shrink `SpecRecord`;
Copy link
Contributor

@adamgundry adamgundry left a comment

Choose a reason for hiding this comment

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

We're getting there! Thanks @adinapoli.

@adinapoli adinapoli requested a review from adamgundry November 6, 2025 14:14
@adamgundry adamgundry changed the title Add shrink default implementation via genericShrink, add genericsTool and dataTypeableTool Generate shrink implementations in quickCheckTool Nov 6, 2025
@adamgundry adamgundry merged commit 8b85714 into master Nov 6, 2025
6 checks passed
@adamgundry adamgundry deleted the adinapoli/issue-84 branch November 6, 2025 15:28
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.

Generate shrink implementations

3 participants