Test des propriétés QuickCheck contre plusieurs types?
-
11-09-2019 - |
Question
I ai un Atomic
de classe de type, qui définit des fonctions de conversion de certains types de / à une valeur d'enveloppe (de Atom
). Je voudrais définir une propriété QuickCheck qui stipule que: « pour toutes les instances de Atomic
, toute valeur peut être stockée et récupérée en toute sécurité ». La propriété ressemble à ceci:
class Atomic a where
toAtom :: a -> Atom
fromAtom :: Atom -> Maybe a
prop_AtomIdentity x = fromAtom (toAtom x) == Just x
Cependant, si j'essaie juste de courir cette propriété par QuickCheck, il prend une seule instance (Bool
) et teste. Je travaille actuellement autour de ce en définissant les signatures de type pour chaque type atomique pris en charge dans la liste des tests, mais c'est bavard et sujette à erreur:
containerTests =
[ run (prop_AtomIdentity :: Bool -> Bool)
, run (prop_AtomIdentity :: Word8 -> Bool)
, run (prop_AtomIdentity :: String -> Bool)
{- etc -} ]
Je suis en train de définir une fonction qui le fera automatiquement:
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
Mais il échoue avec une erreur de typecheck:
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)]
Y at-il une meilleure façon de tester une propriété QC contre plusieurs types? Dans le cas contraire, peuvent forallAtoms être au travail ou est-ce pas pris en charge par le système de type?
La solution
Je ne peux pas compiler votre code, donc ... tir aveugle:
essayer
forallAtoms :: (forall a. (Atomic a, Show a) => a -> Bool) -> [TestOptions -> IO TestResult]
comme une signature de type. Ce besoin de l'extension de la langue de -XRankNTypes.
Le problème que vous avez, comme je le vois, est que GHC essaie de trouver un de type à insérer pour a
dans x :: (a -> Bool)
pour l'ensemble du périmètre de la fonction, mais vous donne déjà trois différents là-bas.