martin | 12 Jul 08:33 2013
Picon

Quick-check: how to generate arbitrary complex data?

Hello all,

I have a type ("Mail") which consists of hash and a list, where the hash
keeps some redundant data of the list for faster access. I can add and
remove elements to values of this type using custom functions, called
push and pop.

Now I wanted to write some quick checks, but I have no clue how to
generate arbitrary values of this type. It will certainly no suffice to
write arbitrary instances for the underlying types (Int and Char),
because the hash and the list need to be synchronized.

Currently "Mail" it is only a type synonym. I suppose as a prerequisite
I need to wrap it into a type constructor. But then what?
Roman Cheplyaka | 12 Jul 09:18 2013

Re: Quick-check: how to generate arbitrary complex data?

* martin <martin.drautzburg <at> web.de> [2013-07-12 08:33:54+0200]
> Hello all,
> 
> I have a type ("Mail") which consists of hash and a list, where the hash
> keeps some redundant data of the list for faster access. I can add and
> remove elements to values of this type using custom functions, called
> push and pop.
> 
> Now I wanted to write some quick checks, but I have no clue how to
> generate arbitrary values of this type. It will certainly no suffice to
> write arbitrary instances for the underlying types (Int and Char),
> because the hash and the list need to be synchronized.
> 
> Currently "Mail" it is only a type synonym. I suppose as a prerequisite
> I need to wrap it into a type constructor. But then what?

QuickCheck's Gen is a functor. So you can generate a list, and then
use fmap to add a hash to it.

  instance Arbitrary HashedList where
    arbitrary = addHashToList <$> arbitrary

Roman
martin | 13 Jul 10:10 2013
Picon

Re: Quick-check: how to generate arbitrary complex data?

Am 07/12/2013 09:18 AM, schrieb Roman Cheplyaka:

> QuickCheck's Gen is a functor. So you can generate a list, and then
> use fmap to add a hash to it.
> 
>   instance Arbitrary HashedList where
>     arbitrary = addHashToList <$> arbitrary
> 

This requires HashedList to be a new type, right? So far my code only
used type synonyms.

Does this mean I have to convert type synonyms into types in order to
use QuickCheck?

Does this mean I have to "plan for QuickCheck" when I design my types?
Aleksey Uymanov | 13 Jul 10:56 2013
Picon

Re: Quick-check: how to generate arbitrary complex data?

On Sat, 13 Jul 2013 10:10:39 +0200
martin <martin.drautzburg <at> web.de> wrote:

> This requires HashedList to be a new type, right? So far my code only
> used type synonyms.
> 
> Does this mean I have to convert type synonyms into types in order to
> use QuickCheck?
> 
> Does this mean I have to "plan for QuickCheck" when I design my types?

You can still create your own Gen manually and have several generators
for different 'types'.

You will need to use 'forAll' combinator to perform the testing like this:

data A
type ListA = [A]
type OtherListA = [A]

genListA :: Gen ListA

genOtherListA :: Gen OtherListA

checkListA :: ListA -> Property

checkOtherListA :: OtherListA -> Property

prop1 = forAll genListA checkListA
prop2 = forAll genOtherListA checkOtherListA 
(Continue reading)

Roman Cheplyaka | 13 Jul 12:16 2013

Re: Quick-check: how to generate arbitrary complex data?

* martin <martin.drautzburg <at> web.de> [2013-07-13 10:10:39+0200]
> Am 07/12/2013 09:18 AM, schrieb Roman Cheplyaka:
> 
> > QuickCheck's Gen is a functor. So you can generate a list, and then
> > use fmap to add a hash to it.
> > 
> >   instance Arbitrary HashedList where
> >     arbitrary = addHashToList <$> arbitrary
> > 
> 
> This requires HashedList to be a new type, right? So far my code only
> used type synonyms.
> 
> Does this mean I have to convert type synonyms into types in order to
> use QuickCheck?

Probably. Technically, you could use OverlappingInstances to provide a
special case for your lists (because they have a spcific shape), but I'd
consider it a kludge in this case.

Or you can avoid defining an instance at all, as Aleksey has pointed
out.

> Does this mean I have to "plan for QuickCheck" when I design my types?

Kind of. It's not really specific to QuickCheck. Every time you want to
give some non-standard instances to your types, you should be using
newtypes or data-types.

More generally, you should be using newtypes or data types every time
(Continue reading)


Gmane