题
我有一个类型的类Atomic
,它用于从一个包装值(Atom
)转化某些类型/定义的功能。我想定义它规定一个快速检查属性:“为Atomic
的所有实例,任何值都可以存储和检索的安全”。的属性是这样的:
class Atomic a where
toAtom :: a -> Atom
fromAtom :: Atom -> Maybe a
prop_AtomIdentity x = fromAtom (toAtom x) == Just x
不过,如果我只是尝试运行通过快速检查该属性,它只是挑选一个实例(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进行工作,或者,不是由类型系统支持?
解决方案
我不能编译你的代码,所以...盲拍:
试
forallAtoms :: (forall a. (Atomic a, Show a) => a -> Bool) -> [TestOptions -> IO TestResult]
作为一种类型的签名。这就需要-XRankNTypes语言的扩展。
您,在我看来,是GHC试图找到问题的一个的类型中插入用于a
整个功能范围x :: (a -> Bool)
,但你已经给三个不同的存在。
不隶属于 StackOverflow