[Haskell-cafe] QuickCheck Questions

Kevin Quick quick at sparq.org
Sun Jul 24 21:14:24 CEST 2011


On Sun, 24 Jul 2011 07:30:56 -0700, Mark Spezzano  
<mark.spezzano at chariot.net.au> wrote:

> Hi all,
>
> I would appreciate it if someone can point me in the right direction  
> with the following problem.
>
> I'm deliberately implementing a naive Queues packages that uses finite  
> lists as the underlying representation. I've already read through  
> Hughes' paper and the article in The Fun of Programming, but I'm still  
> having some difficulties. Specifically:
>
> 1. I have a newtype Queue a = Queue [a] and I want to generate Queues of  
> random Integers that are also of random size. How do I do this in  
> QuickCheck? I guess that  I need to write a generator and then make my  
> "Queue a" concrete type an instance of Arbitrary? How?

Mark,

One of the great things about QuickCheck is that it is automatically  
compositional.
What I mean by this is that all you need in your instance is how to form a  
"Queue [a]" given "[a]", because there are already QuickCheck instances  
for forming lists, and as long as a is pretty standard (Integers is fine)  
then there's likely an Arbitrary instance for that as well.

So (from my head, not actually tested in GHC):

import Control.Applicative
import Test.QuickCheck

instance Arbitrary Queue where
    arbitrary = Queue <$> arbitrary

Then you can use this as:

testProperty "length is something" propQInts

propQInts t = length t == ....
     where types = (t :: Queue Integers)

The where clause is a fancy way of specifying what the type of t should be  
without having to express the overall type of propQInts.  You could use a  
more conventional type specification as well.

>
> 2. If I wanted to specify/constrain the ranges of random Integers  
> generated, how would I do this?

Probably something like this:

instance Arbitrary Queue where
     arbitrary = do li <- listOf $ arbitrary
		   lr <- liftM $ map rangelimit li
		   return $ Queue lr
                 where rangelimit n = case (n < LOW, n > HIGH) of
					(True,_) -> LOW
					(_,True) -> HIGH
					_ -> n


>
> 3. If I wanted to specify/constrain the Queue sizes how would I do this?

Similar to #2.  Perhaps:

    arbitrary = arbitrary >>= (return . Queue . take CNT . listOf)


-- 
-KQ



More information about the Haskell-Cafe mailing list