I have a type class Atomic
, which defines functions for converting certain types to/from a wrapper value (Atom
). I'd like to define a QuickCheck property which states: "for all instances of Atomic
, any value may be stored and retrieved safely". The property looks like this:
class Atomic a where
toAtom :: a -> Atom
fromAtom :: Atom -> Maybe a
prop_AtomIdentity x = fromAtom (toAtom x) == Just x
However, if I just try to run that property through QuickCheck, it just picks one instance (Bool
) and tests it. I'm currently working around that by defining type signatures for each supported atomic type in the test list, but this is verbose and error-prone:
containerTests =
[ run (prop_AtomIdentity :: Bool -> Bool)
, run (prop_AtomIdentity :: Word8 -> Bool)
, run (prop_AtomIdentity :: String -> Bool)
{- etc -} ]
I'm trying to define a function which will do this automatically:
forallAtoms :: (Atomic a, Show a) => (a -> Bool) -> [TestOptions -> IO TestResult]
forallAtoms x =
[ run (x :: Bool -> Bool)
, run (x :: Word8 -> Bool)
, run (x :: String -> Bool)
{- etc -} ]
containerTests = forallAtoms prop_AtomIdentity
But it fails with a typecheck error:
Tests/Containers.hs:33:0:
Couldn't match expected type `Word8' against inferred type `String'
In the first argument of `run', namely `(x :: Word8 -> Bool)'
In the expression: run (x :: Word8 -> Bool)
In the expression:
[run (x :: Bool -> Bool), run (x :: Word8 -> Bool),
run (x :: String -> Bool)]
Is there a better way to test a QC property against multiple types? If not, can forallAtoms be made to work or is that not supported by the type system?
I cannot compile your code, so ... blind shot:
try
forallAtoms :: (forall a. (Atomic a, Show a) => a -> Bool) -> [TestOptions -> IO TestResult]
as a type signature. This needs the -XRankNTypes language extension.
The problem you have, as I see it, is that GHC tries to find one type to insert for a
in x :: (a -> Bool)
for the entire function scope, but you already give three different there.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With