8
votes

I've a function, rev, that returns some value for a type that is in three typeclasses:

rev :: (Integral a, Show a, Read a) => a -> a
rev = read . reverse . show

I'd like to test some property about it with quickcheck. Though, I'm not interested in testing negative values of Integral types because I'm using Integer by lack of a Natural type in the base library. So I thought, let's take the opposite of the value generated when the value generated is negative and I'll be fine:

prop_id :: (Integral a, Show a, Read a) => Positive a -> Bool
prop_id n | n >= 0    = (rev.rev) n == n
          | otherwise = let n' = -n in (rev.rev) n' == n'

(the property tested isn't important here - in particular it doesn't hold for very basic values and I'm aware of that, it's not the subject of this question)

Then I ran into the Positive modifier and thought that although my test was now functionning, it'd be nice to implement it in a nicer way. So I tried:

prop_id :: (Integral a, Show a, Read a) => Positive a -> Bool
prop_id n = (rev.rev) n == n

I must admit I was surprised when it compiled. But then an error popped when running the test:

*** Failed! Exception: 'Prelude.read: no parse' (after 1 test): 
Positive {getPositive = 1}

So I thought, "mmk, must declare this Positive thing an instance of Read". So I did just that, but the instance is already declared in the quickCheck library it seems because ghci screamed at me.

And at this point I'm lost, for I do not find good documentation (if any).

Any pointer helping me to understand modifiers and other nice things in the quickcheck library will be appreciated.

1
There's no parse because rev (Positive {getPositive = 1}) is read "}1 = evitisoPteg{ evitisoP".Daniel Wagner

1 Answers

19
votes

The common way of using these modifiers is to pattern match on them, e.g.

prop_id :: (Integral a, Show a, Read a) => Positive a -> Bool
prop_id (Positive n) = (rev.rev) n == n

This way, n will have the underlying type.