SmallCheck:使类型为Serial的类型实例 [英] SmallCheck: Making types instance of typeclass Serial
问题描述
我试图弄清楚如何结合使用基于smallcheck属性的测试库和好吃的东西.
I'm trying to figure out how to use the smallcheck property-based test library in conjunction with tasty.
我遇到了多字段记录类型的问题:如何创建一个记录类型,该记录类型的Serial
类型类的成员不超过4个字段?
I ran into a problem with multi-field record types: How can I make a record type with mor than 4 fields member of the Serial
typeclass?
我认为这是正常的做法:
I assume that this would be the normal way to go:
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
import Test.Tasty
import Test.Tasty.SmallCheck
import Test.SmallCheck.Series
data T1 = T1 { p1 :: Int,
p2 :: Char,
p3 :: [Int]
} deriving (Show, Eq)
instance (Monad m) => Serial m T1 where
series = cons3 T1
main :: IO ()
main = defaultMain tests
tests :: TestTree
tests = testGroup "Tests" [scProps]
scProps = testGroup "(checked by SmallCheck)"
[ testProperty "Test1" prop_test1
]
prop_test1 x y = x == y
where types = (x :: T1, y :: T1)
这有效,当然"Test1"失败.但是,此方法不适用于具有4个以上字段的记录类型,因为consN
函数仅定义为最多包含4个参数.这是链接到模块的Test.SmallCheck.Series
声明函数的位置.
This works and of course 'Test1' fails. However this approach does not work for record types with more than 4 fields because the consN
function is only defined to take up to 4 parameters. Here's a link to the module Test.SmallCheck.Series
where the function is declared.
对于类似的东西
data T1 = T1 { p1 :: Int,
p2 :: Char,
p3 :: Int,
p4 :: Int,
p5 :: [Int]
} deriving (Show, Eq)
将其添加到Serial
的方式是什么?我试过使用这样的泛型:
what is the way to add it to Serial
? I tried using generics like this:
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
{-# LANGUAGE DeriveGeneric #-}
import Test.Tasty
import Test.Tasty.SmallCheck
import Test.SmallCheck.Series
import GHC.Generics
data T1 = T1 { p1 :: Int,
p2 :: Char,
p3 :: [Int]
} deriving (Show, Generic)
instance Serial m a => Serial m T1
但是ghc拒绝接受上面的示例并显示以下消息:
But ghc refuses to accept the above example with the following message:
Variable occurs more often in a constraint than in the instance head
in the constraint: Serial m a
(Use -XUndecidableInstances to permit this)
In the instance declaration for `Serial m T1'
非常感谢!
法律
推荐答案
例如cons3
在SmallCheck中定义:
Here's how e.g. cons3
is defined in SmallCheck:
cons3 :: (Serial m a, Serial m b, Serial m c) =>
(a->b->c->d) -> Series m d
cons3 f = decDepth $
f <$> series
<~> series
<~> series
因此,以此类推,这就是您使用任何数字为类型定义实例的方式 字段:
So, by analogy, here's how you define the instance for your type with any number of fields:
instance Monad m => Serial m T1 where
series = decDepth $
T1 <$> series <~> series <~> series <~> series <~> series
(以上定义中的每个series
都对应于您数据的一个字段
结构).
(every series
in the definition above corresponds to one field of your data
structure).
关于您的泛型代码,它应如下所示:
Regarding your Generics code, it should look like this:
instance Monad m => Serial m T1
这里没有a
,因此您的约束是多余的(实际上会导致问题).
There's no a
here, so your constraint is superfluous (and actually leads to problems).
这篇关于SmallCheck:使类型为Serial的类型实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!