[QuickCheck] Generic Arbitrary instance using GHC generics?
Bradford Larsen
brad.larsen at gmail.com
Tue Dec 1 19:54:25 GMT 2015
I've recently been using QuickCheck, and was a bit surprised to find that I
have to manually define `Arbitrary` instances for all my data types. In
simple cases, this probably shouldn't be necessary!
I searched for existing work on a generic `Arbitrary` instance, and found
only this Haskell Cafe thread from 2013:
https://groups.google.com/forum/#!topic/haskell-cafe/zaDyN9qHjeM. One
comment there mentions an unmerged QuickCheck branch with generic Arbitrary
support, but I haven't found it.
Using GHC Generics, it seems relatively straightforward to define a generic
function for producing test inputs for QuickCheck.
Two questions:
- Am I just overlooking already-existing generic Arbitrary support?
- Are there pitfalls that I'm not aware of that make it difficult to add
generic Arbitrary support?
Thanks,
Brad
A GHC Generics-based solution might look something like this:
class GArbitrary f where
garbitrary :: Gen (f a)
instance GArbitrary V1 where
garbitrary = undefined
instance GArbitrary U1 where
garbitrary = pure U1
instance (Generic c, GArbitrary (Rep c)) => GArbitrary (K1 i c) where
garbitrary = K1 . to <$> garbitrary
-- Note: this instance doesn't evenly select from sums with more
-- than 2 constructors
instance (GArbitrary f, GArbitrary g) => GArbitrary (f :+: g) where
garbitrary = oneof [ L1 <$> garbitrary, R1 <$> garbitrary ]
instance (GArbitrary f, GArbitrary g) => GArbitrary (f :*: g) where
garbitrary = (:*:) <$> garbitrary <*> garbitrary
instance (GArbitrary f) => GArbitrary (M1 i c f) where
garbitrary = M1 <$> garbitrary
instance (GArbitrary f, GArbitrary g) => GArbitrary (f :.: g) where
garbitrary = Comp1 <$> garbitrary
genericArbitrary :: (GArbitrary (Rep a), Generic a) => Gen a
genericArbitrary = fmap to garbitrary
Then, we could add a default signature for `arbitrary` in QuickCheck's
`Arbitrary` class, using `genericArbitrary`, and automatically generate
test cases for many data types.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://projects.haskell.org/pipermail/quickcheck/attachments/20151201/f73c0cf8/attachment.htm>
More information about the QuickCheck
mailing list