2

我试图弄清楚如何将 smallcheck 基于属性的测试库与美味结合使用。

我遇到了多字段记录类型的问题:如何使用类型类的 4 个以上字段成员创建记录Serial类型?

我认为这将是正常的方法:

{-# 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

对于类似的东西:

data T1 = T1 { p1 :: Int,
               p2 :: Char,
               p3 :: Int,
               p4 :: Int,
               p5 :: [Int]
             } deriving (Show, Eq)

添加它的方法是什么Serial?我尝试使用这样的泛型:

{-# 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 拒绝接受上述示例,并显示以下消息:

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'

提前谢谢了!

朱尔斯

4

1 回答 1

3

以下cons3是在 SmallCheck 中定义 eg 的方式:

cons3 :: (Serial m a, Serial m b, Serial m c) =>
         (a->b->c->d) -> Series m d
cons3 f = decDepth $
  f <$> series
    <~> series
    <~> series

因此,以此类推,以下是您如何使用任意数量的字段为您的类型定义实例:

instance Monad m => Serial m T1 where
  series = decDepth $
    T1 <$> series <~> series <~> series <~> series <~> series

series上面定义中的每一个都对应于数据结构的一个字段)。

关于您的泛型代码,它应该如下所示:

 instance Monad m => Serial m T1

这里没有a,所以你的约束是多余的(实际上会导致问题)。

于 2013-12-14T09:37:14.897 回答