I'm trying to run QuickCheck on some nested lists, something that looks like this:
type Constraint = Text
data Value = Value [Constraint]
data Literal = Literal Value [Value]
type Formula = [Literal]
So a formula is a list of literals, each of which contains a predicate and some arguments; predicate/arguments are values which are a disjunction of constraints in string form each. That gives us a list of lists of lists of lists, phew!
If one of my QuickCheck properties fails, I tend to get an incomprehensible pageful of output. Before experimenting with shrink, I used to get around this by having arbitrary instances that could only generate a small set of (small) values. Implementing the shrink function for each of my types seems to help a little, but not as much as I'd like. I still get a pageful of output.
I think what I want from shrink is a small list of literals, where each literal has a small list of values, which in turn has few constrains, each of which is as short as possible. But in my current efforts, at least of these lists gets big enough to make the output horrible. If I try to tune my shrink implementations, I also find that QC starts taking a very long time (searching for shrinks?), which kind of dampens my efforts to shrink effectively.
How do you improve your chances of understanding QuickCheck failures when you have nested data like this?
take 5 <$> arbitrary
), which I still seem to be finding bugs with – Colquitt?X/cat|dog
to mean label constrained to unify with only "cat" or "dog" (no label in my simplified code above). On top of this a function that does unification on formulas, and on top of that a function that expands another macro data structure (containing formulas). I wanted to check that the formulas in my expanded macros subsume the formulas in the original (ie. the template) – Colquitt