quickcheck-higherorder
                                
                                 quickcheck-higherorder copied to clipboard
                                
                                    quickcheck-higherorder copied to clipboard
                            
                            
                            
                        More Constructible instances
- Types from base and QuickCheck
- Generic types
How much work would the generic types be?
It seems pretty straightforward to get to a working state, but I have some minor concerns about packaging and the API around Arbitrary.
The main and straightforward part is to define Repr a and fromRepr by induction on the generic representation Rep a, GHC.Generics 101-level recipe, no surprises there.
For the superclass constraints Arbitrary (Repr a) and Show (Repr a) you can pull in generic-random and generic-data, which brings me to the following points:
- They are extra dependencies, and they seem heavy enough to put this machinery in (yet) another package.
- For ArbitraryI imagine most users would already be content with some default settings, but it also doesn't seem too hard to make available the various knobs ofgeneric-random.
(2) could just be me overthinking. (1) needs some decision to be made, but if you agree with it you can just create another package.
(EDIT: I forgot to mention shrinking, QuickCheck has a generic implementation we can just reuse)
I think we could entirely offload those instances, right? eg instance Arbitrary a => Arbitrary (K1 _1 a) --- plus some newtype wrappers to not make this an orphan. I'm not sure why you'd need generic-random and generic-data.
The problem is with sums, that you don't know with what probability to go left or right. You can set that probability arbitrarily, but by definition that's going to be arbitrary and inflexible.
generic-data would be used to derive Show for a type computed from a generic representation. For example, if you want a Constructible instance for:
data MyType = MyCons (Int -> Int)
  -- No instances
you somehow need to define its Repr:
data ReprMyType = ReprMyCons (Int :-> Int)
  deriving (Show, Arbitrary)
except that with generics you don't have the ability to declare data types, so what do you do?
Hmm, that seems rather involved. Could you instead Replace (->) (:->) (Rep a) as the Repr, and then use from <$> arbitrary @a + some barbies magic to get the Arbitrary (Repr a) instance? This is essentially how higgledy works.
That can work, but it's actually even more involved.
Could you instead
Replace (->) (:->) (Rep a)as theRepr
I was imagining something even simpler, mapping Repr to every field (K1) of the Rep, and letting that take care of the substitution recursively.
and then use
from <$> arbitrary @a+ some barbies magic to get theArbitrary (Repr a)instance?
It seems the main idea is to somehow make a function a -> Repr a, and then fmap that function over arbitrary; that is essentially what QuickCheck does for Fun. That can be done and added to this library too, but:
- 
We'll have to copy QuickCheck's Functionclass (and many instances) and adapt it to test-fun; that's a much more involved task than derivingArbitrary (Repr a)directly from the generic structure ofRepr a.
- 
it's only going to work for types containing at most first-order functions (more precisely, whose domains have decidable equality)