有没有办法在 Haskell QuickCheck 中以这种方式生成用于测试的值?

时间:2021-04-19 22:44:23

标签: haskell quickcheck

我有两种数据类型用于表示一元系统中的自然数

data Valoare_Unar = Unu deriving(Show);
data Numar_Unar = Invalid | Unar [Valoare_Unar] deriving(Show);

我有这些函数可以将此数字从整数转换为我的数据类型,反之亦然。

convert :: Unar.Numar_Unar -> Integer
convert Unar.Invalid = (-1)
convert (Unar.Unar xs)
    | null xs   = 0
    | otherwise = 1 + convert (Unar.Unar (tail xs))

convert' :: Integer -> Unar.Numar_Unar
convert' (-1) = Unar.Invalid
convert' x = fromInteger x :: Unar.Numar_Unar

我想测试 (convert' (convert _)) == _ 并且我有 prop_check xs = Utils.convert' (Utils.convert xs) == xs where types = xs::Unar.Numar_Unar

我已经创建了任意数据类型的实例,但是我在弄清楚应该如何为“Unar”构造函数生成值时遇到了问题。

instance Arbitrary Valoare_Unar where
        arbitrary = elements [Unu]

instance Arbitrary Numar_Unar where
    arbitrary = elements [Invalid, Unar []]

使用 QC.verboseCheck prop_check 我注意到唯一的测试值是“Invalid”和“Unar[]”。

我的问题是:如何生成“Unar[Unu] ; Unar[Unu,Unu,Unu] ; ... ; Unar [Unu,..,Unu]”之类的值来进行测试?

编辑:实例 Num Numar_Unar

instance Num Numar_Unar where
    (+) (Unar xs) (Unar ys)
        | null ys   = (Unar xs)
        | otherwise = (+) (Unar (xs ++ [head ys])) (Unar (tail ys))
    (+) _ _ = Invalid
    (-) (Unar xs) (Unar ys)
        | length xs < length ys = Invalid
        | null ys               = Unar xs
        | xs == ys              = Unar []
        | otherwise             = (-) (Unar (tail xs)) (Unar (tail ys))
    (-) _ _ = Invalid
    (*) (Unar xs) (Unar ys)
        | null ys   = Unar []
        | otherwise = (+) (Unar xs) ((*) (Unar xs) (Unar (tail ys)))
    (*) _ _ = Invalid
    abs (Unar xs)   = Unar xs
    abs Invalid     = Invalid

    signum (Unar xs)
        | null xs   = Unar []
        | otherwise = Unar [Unu]
    signum Invalid  = Invalid
    fromInteger x 
        | x < 0     = Invalid
        | x == 0    = Unar []
        | otherwise = (+) (Unar [Unu]) (fromInteger (x-1))

1 个答案:

答案 0 :(得分:2)

arbitrary = elements [Invalid, Unar []] 的意思是“当我在这种类型上运行 arbitrary 时,总是给我 InvalidUnar []”。一个合适的 Arbitrary 实例如下所示:

instance Arbitrary Numar_Unar where
    arbitrary = frequency [(1, return Invalid), (3, Unar <$> arbitrary)]

这将使 arbitrary 生成 Invalid 1/4 的时间和 Unar 3/4 的时间。当它生成 Unar 时,它会为 arbitrary 类型调用 [Valoare_Unar] 以获取包含随机元素数量而不是始终没有元素的列表。您还应该考虑向类添加一个 shrink 方法,如下所示:

    shrink Invalid = []
    shrink (Unar []) = [Invalid]
    shrink (Unar (Unu:xs)) = [Invalid, Unar [], Unar xs]