Pergunta

Eu tenho um Atomic tipo de classe, que define funções para converter certos tipos de / para um valor invólucro (Atom). Eu gostaria de definir uma propriedade QuickCheck que afirma: "para todas as instâncias de Atomic, qualquer valor podem ser armazenados e recuperados com segurança". O hotel parece como este:

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

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

No entanto, se eu tentar executar essa propriedade através QuickCheck, ele só pega uma instância (Bool) e testes de TI. Atualmente estou trabalhando em torno de que, ao definir assinaturas de tipo para cada tipo atômica suportado na lista de teste, mas isso é detalhado e-propensa a erros:

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

Estou tentando definir uma função que irá fazer isso automaticamente:

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

Mas ele falha com um erro 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)]

Existe uma maneira melhor para testar uma propriedade QC contra vários tipos? Se não, forallAtoms pode ser feita para o trabalho ou se que não é suportado pelo sistema de tipo?

Foi útil?

Solução

Não consigo compilar o código, então ... cego tiro:

try

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

como uma assinatura tipo. Este precisa da extensão da linguagem -XRankNTypes.

O problema que você tem, a meu ver, é que GHC tenta encontrar um digite para inserir para a em x :: (a -> Bool) para todo o escopo de função, mas você já dão três diferentes lá.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top