Applicative vs Monadic generators
So, I've read that one should avoid monadic generators in general due to reducing the effectiveness of shrinking. Does this imply that using
{-# LANGUAGE ApplicativeDo #-}
{-# OPTIONS_GHC -foptimal-applicative-do #-}
anywhere I define a new generator is a good idea? (I'm okay with the longer compile time if it means better shrinking; but of course, one can always remove the optimal flag.)
If so, does this suggest using ApplicativeDo globally in Hedgehog is a good idea, given how much monadic manipulation of Trees occurs in the library?
I've also wondered this! I've also wondered if we would benefit from GenA and GenM to be really explicit - GenA being a Gen that only has an Applicative instance, and GenM being the variant that supports Monad. You'd also need a natural transformation from GenA to GenM
For shrinking, I don't see any advantage to use monadic behavior when applicative behavior is possible.
Semi-related question - would this also reduce the space leaks that occur during shrinking? Whenever I run a test on my workstation which doesn't have a swap partition, I have to keep an eye on memory usage; whenever a failing test occurs, shrinking it often (maybe... 15% of the time?) quickly eats up all of my RAM and freezes, resulting in my workstation requiring a hard power reset.
Maybe, but it certainly should not. That is definitely a bug. It would be great if you could find (and share) a small example that consistently reproduces that behavior.
Unfortunately it seems to come and go; mainly with deep and wide recursive structures (think SAT/SMT formulas). It's also quite possibly unrelated to Hedgehog itself, and due to the nature of telemetry collection while shrinking x3