gpt4 book ai didi

list - List 的应用实例在使用 QuickCheck/Checkers 的组合律测试中永远运行

转载 作者:行者123 更新时间:2023-12-04 21:09:39 25 4
gpt4 key购买 nike

我想使用我自定义的列表来实现列表的常规应用实例:

import Control.Monad

import Test.QuickCheck
import Test.QuickCheck.Checkers
import Test.QuickCheck.Classes

data List a =
Nil
| Cons a (List a)
deriving (Eq, Ord, Show)


instance Functor List where
fmap f (Cons x xs) = Cons (f x) (fmap f xs)
fmap f Nil = Nil


instance Applicative List where
pure x = Cons x Nil
(<*>) Nil _ = Nil
(<*>) _ Nil = Nil
(<*>) (Cons f fs) xs = (+++) (fmap f xs) (fs <*> xs)

(+++) :: List a -> List a -> List a
(+++) (Cons x Nil) ys = Cons x ys
(+++) (Cons x xs) ys = Cons x xs'
where xs' = (+++) xs ys

instance Arbitrary a => Arbitrary (List a) where
arbitrary = sized go
where go 0 = pure Nil
go n = do
xs <- go (n - 1)
x <- arbitrary
return (Cons x xs)

instance (Eq a) => EqProp (List a) where
(=-=) = eq

main = do
let trigger = undefined :: List (Int, String, Int)
quickBatch $ applicative trigger

我的代码通过了 Checkers 中的所有应用测试,除了一个组合法。测试组合律时不会出错,只是永远不会完成。

我的代码是否会以某种我看不到的方式永远重复出现,或者只是测试合成定律的速度非常慢?

如果我在 Checkers 执行期间使用 control-c,则会收到以下错误消息:
applicative:
identity: +++ OK, passed 500 tests.
composition: *** Failed! Exception: 'user interrupt' (after 66 tests):
Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> Nil))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> (Cons <function> Nil))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
Cons (-61) (Cons (-24) (Cons 56 (Cons (-10) (Cons 28 (Cons 5 (Cons (-5) (Cons 33 (Cons 18 (Cons 47 (Cons 43 (Cons 43 (Cons (-58) (Cons 35 (Cons (-52) (Cons (-52) (Cons (-41) (Cons 3 (Cons (-7) (Cons (-53) (Cons (-22) (Cons (-20) (Cons (-12) (Cons 46 (Cons (-53) (Cons 35 (Cons (-31) (Cons (-10) (Cons 43 (Cons (-16) (Cons 47 (Cons 53 (Cons 22 (Cons 8 (Cons 1 (Cons (-64) (Cons (-39) (Cons (-57) (Cons 34 (Cons (-31) (Cons 20 (Cons (-39) (Cons (-47) (Cons (-59) (Cons 15 (Cons (-42) (Cons (-31) (Cons 4 (Cons (-62) (Cons (-14) (Cons (-24) (Cons 47 (Cons 42 (Cons 61 (Cons 29 (Cons (-25) (Cons 30 (Cons (-20) (Cons 16 (Cons (-30) (Cons (-38) (Cons (-7) (Cons 16 (Cons 19 (Cons 20 Nil))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
homomorphism: +++ OK, passed 500 tests.
interchange: +++ OK, passed 500 tests.
functor: +++ OK, passed 500 tests.

如果其中一个功能很慢,我猜它是 (+++) ,但我不知道 GHC 如何很好地执行代码以理解原因。

更新:

组成规律是:
pure (.) <*> u <*> v <*> w = u <*> (v <*> w)

我可以用我的代码展示它的简单示例:
Cons (+1) Nil <*> (Cons (*2) Nil <*> Cons 1 (Cons 2 (Cons 3 Nil)))


pure (.) <*> Cons (+1) Nil <*> Cons (*2) Nil <*> Cons 1 (Cons 2 (Cons 3 Nil))

两者都给出相同的结果,所以为什么组合法永远不会结束让我很困惑。这可能是 checkers 的问题吗?图书馆?

最佳答案

我的第一个想法是 go得到一个否定的论点并循环。但是,当修改它以使用 trace如果 n < 0 则抛出错误,我发现它要简单得多:您的代码真的很慢。

这是我修改的部分(go' 用于跟踪,但我将其短路以进行基准测试):

import Debug.Trace

(+++) :: List a -> List a -> List a
{-# INLINE (+++) #-}
(+++) (Cons x Nil) ys = Cons x ys
(+++) (Cons x xs) ys = Cons x xs'
where xs' = (+++) xs ys

maxListSize = 10

instance Arbitrary a => Arbitrary (List a) where
arbitrary = sized go''
where
go'' n = go' $ mod n maxListSize
go' n = if n < 0 then error ("bad n:" ++ show n) else trace (show n ++ " , ") $ go n
go 0 = pure Nil
go n = do
xs <- go' (n - 1)
x <- arbitrary
return (Cons x xs)

检查某种无限循环的跟踪,我发现事情从未停止过, n不断下降,然后弹出下一次测试。当它变慢时,一次测试只需要几秒钟。请记住,您尝试运行 500 个测试。

我的基准测试并不严格,但这就是我得到的( x 是模数,在 [1..18] 范围内):

Time Plot (x is modulus, y is seconds)

发现快速回归 5.72238 - 2.8458 x + 0.365263 x^2 .当我运行跟踪时, n不断增加。虽然我不确定测试是如何运行的,但如果它增加 n每个测试,然后 n最多可达 500 .

这个公式并不公平,但让我们假设它是一个不错的界限。 (我认为应该是因为算法是 O(n^2) 。)

然后在我的机器上运行所有测试大约需要 25 个小时。

附言由于所有测试都通过了 n 的合理范围而且我找不到错误,我认为您的代码是正确的。

关于list - List 的应用实例在使用 QuickCheck/Checkers 的组合律测试中永远运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37331336/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com