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?

Était-ce utile?

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top