Last updated: 2017-07-28 13:21:56 +0100
Upstream URL: git clone http://chriswarbo.net/git/runtime-arbitrary.git
Contents of README follows
Obtain data generators at run time, from instances of
Arbitrary
.
We define one function with the following (simplified) signature
RuntimeArbitrary.getArbGen :: Typeable a => proxy a -> [Gen a]
The proxy
type constructor can be anything, whatever
makes it easiest to provide the argument. For example
[] :: [Foo]
is a perfectly good argument, as long as
Foo
is Typeable
.
The resulting list will contain the arbitrary
method of
the Arbitrary
type class, if a suitable instance is in
scope at initialisation time (see below). If not, an empty list is
returned. (Really, this is a Maybe (Gen a)
rather than a
[Gen a]
, but it’s less verbose to manipulate lists than
maybes).
Initialisation is required to find instances, and requires the following line appear somewhere in your module (or one of its imports):
mkIfCxtInstances ''Arbitrary
This is Template Haskell, and uses the IfCxt
module from
the ifcxt
package, so you must have all of those things
enabled/imported. This is where the magic happens.
Conceptually, this initialisation line generates, at compile time, a
Map of all Arbitrary
instances which are in-scope at that
point (i.e. available via imports), indexed by type rep. At run time,
when we execute a call to getArbGen
, it simply looks up the
given type rep in this Map, to get the corresponding
arbitrary
method.
Since Template Haskell cannot (yet) manipulate a module’s imports,
this need to initialise “manually” seems unavoidable (if
runtime-arbitrary
did this initialisation for you, only
those instances we decide to import would be available; with no
extension mechanism).