Тестирование свойств QuickCheck для нескольких типов? - PullRequest
12 голосов
/ 19 сентября 2009

У меня есть класс типов Atomic, который определяет функции для преобразования определенных типов в / из значения оболочки (Atom). Я хотел бы определить свойство QuickCheck, которое гласит: «для всех экземпляров Atomic любое значение может быть безопасно сохранено и получено». Свойство выглядит так:

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

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

Однако, если я просто пытаюсь запустить это свойство через QuickCheck, он просто выбирает один экземпляр (Bool) и проверяет его. В настоящее время я работаю над этим, определяя сигнатуры типов для каждого поддерживаемого атомарного типа в тестовом списке, но это многословно и подвержено ошибкам:

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

Я пытаюсь определить функцию, которая будет делать это автоматически:

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

Но происходит сбой при ошибке проверки типа:

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

Есть ли лучший способ проверить свойство QC для нескольких типов? Если нет, можно ли заставить forallAtoms работать или это не поддерживается системой типов?

1 Ответ

12 голосов
/ 19 сентября 2009

Я не могу скомпилировать ваш код, так что ... слепой выстрел:

попробовать

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

как подпись типа. Для этого требуется расширение языка -XRankNTypes.

Проблема, с которой вы сталкиваетесь, на мой взгляд, состоит в том, что GHC пытается найти один тип для вставки для a в x :: (a -> Bool) для всей области действия функции, но вы уже даете три разных там .

...