I have a function that takes a ResponseCode from Network.HTTP. In order to test it with QuickCheck, I wanted to write an instance of Arbitrary for ResponseCode. (In case you don't know, a ResponseCode is just a triple of ints in that library: type ResponseCode = (Int, Int, Int)).
So I wrote something like this:
instance Arbitrary ResponseCode where
arbitrary = triple ( elements [1..6] )
where triple f = (f, f, f)
First of all, GHC complains that the way I'm using types is not standard haskell so I would have to use some compiler flags (which is not really what I want since I feel like there must be an easy solution for this simple problem without flags).
Secondly, my arbitrary function has the wrong type, which is pretty obvious. But then I really didn't figure out how to write a function that returns a triple with random Ints ranging from 1-6.
I would appreciate if somebody could help me out here.
Thank you.
First of all, there is already are these two instances:
instance Arbitrary Int
instance (Arbitrary a, Arbitrary b, Arbitrary c) =>
Arbitrary (a, b, c)
This means that (Int,Int,Int) is already an instance of Arbitrary. This means that the type synonym ResponseCode is already an instance. You cannot define and use a second instance.
You could try using Test.QuickCheck.Gen.suchThat but I hypothesize that it will not work well in this case. If you can, I suggest using a newtype wrapper:
import Test.QuickCheck
import Network.HTTP.Base
import Control.Applicative
import System.Random
newtype Arb'ResponseCode = Arb'ResponseCode { arb'ResponseCode :: ResponseCode }
deriving (Show)
instance Arbitrary Arb'ResponseCode where
arbitrary = do
responseCode <- (,,) <$> f <*> f <*> f
return (Arb'ResponseCode responseCode)
where f = elements [1..6]
-- To use this you can call
-- (fmap arb'ResponseCode arbitrary)
-- instead of just (arbitrary)
Or perhaps use the built-in (Int,Int,Int) instance and post-process the three elements with (succ . (mod
6)).