Frage

Ich habe eine Typklasse Atomic, die Funktionen für die Umwandlung von bestimmten Typen zu / von einem Wrapper-Wert (Atom) definiert. Ich möchte einen Quick Check-Eigenschaft definieren, in dem es heißt: „für alle Instanzen Atomic kann jeder beliebige Wert sicher gespeichert und abgerufen werden“. Die Eigenschaft sieht wie folgt aus:

class Atomic a where
    toAtom :: a -> Atom
    fromAtom :: Atom -> Maybe a

prop_AtomIdentity x = fromAtom (toAtom x) == Just x

Allerdings, wenn ich versuche gerade diese Eigenschaft durch Quick Check zu laufen, es nimmt nur eine Instanz (Bool) und Tests es. Ich arbeite zur Zeit um die durch für jeden unterstützten Atomtyp in der Testliste Typen Signaturen definiert, aber dies ist ausführlich und fehleranfällige:

containerTests =
    [ run (prop_AtomIdentity :: Bool -> Bool)
    , run (prop_AtomIdentity :: Word8 -> Bool)
    , run (prop_AtomIdentity :: String -> Bool)
    {- etc -} ]

Ich versuche, eine Funktion zu definieren, die dies automatisch tun:

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

Aber es scheitert mit einem typecheck Fehler:

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)]

Gibt es einen besseren Weg, um eine QC Eigenschaft gegen mehrere Typen zu testen? Wenn nicht, kann forallAtoms gemacht werden, um zu arbeiten, oder ist das nicht vom Typ System unterstützt?

War es hilfreich?

Lösung

Ich kann den Code nicht kompilieren, so ... Blindschuss:

Versuch

forallAtoms :: (forall a. (Atomic a, Show a) => a -> Bool) -> [TestOptions -> IO TestResult]

als eine Art Signatur. Dies muss die -XRankNTypes Spracherweiterung.

Das Problem, das Sie haben, wie ich es sehe, ist, dass GHC zu finden versucht, ein Typ für a in x :: (a -> Bool) für den gesamten Funktionsumfang einzusetzen, aber man bereits drei verschiedene dort geben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top