SmallCheck:使类型为Serial的类型实例 [英] SmallCheck: Making types instance of typeclass Serial

查看:108
本文介绍了SmallCheck:使类型为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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆