Haskell 如何使用QuickCheck测试函数是否终止?
我想使用QuickCheck测试一个函数,以确保它终止(没有无限递归,没有抛出异常,等等)。这就是我目前所做的:Haskell 如何使用QuickCheck测试函数是否终止?,haskell,quickcheck,Haskell,Quickcheck,我想使用QuickCheck测试一个函数,以确保它终止(没有无限递归,没有抛出异常,等等)。这就是我目前所做的: f :: Int -> Int -> Int prop_fTerminates :: Int -> Int -> Bool -- say prop_fTerminates x y = f x y `seq` True 有没有更好的(更具表现力和惯用性的)方法?这是最好的方法。没有任何算法能够告诉您函数是否终止 特别是,如果您愿意等待足够长的时间,您可能
f :: Int -> Int -> Int
prop_fTerminates :: Int -> Int -> Bool -- say
prop_fTerminates x y = f x y `seq` True
有没有更好的(更具表现力和惯用性的)方法?这是最好的方法。没有任何算法能够告诉您函数是否终止
特别是,如果您愿意等待足够长的时间,您可能会得到一个积极的结果(即,如果函数确实终止,此命题将告诉您)。但是仅仅通过等待,您永远不会知道这个函数没有终止和这个函数还没有终止之间的区别
您可以执行一个检查,如此函数是否在时间T内终止,这可能适合您的需要
编辑如前所述,您的函数不满足您的要求。考虑
> let f = 1:f
> f `seq` True
True
原因是seq
的计算结果仅为。相反,您可以使用深入评估数据结构的deepseq
> import Control.DeepSeq (deepseq)
> f `deepseq` True
* never returns *
我可能不会费心,我只是测试它输出的其他属性 任何以任何方式检查
fxy
输出的属性都至少要执行与属性的终止检查一样多的终止检查,那么为什么要浪费时间加倍检查呢
如果出于某种原因,“fxy终止”是您可以测试的关于f
的唯一属性,那么您得到的似乎是合理的。我不想证明函数终止(这是停止问题),我只想确保我在实现中没有犯任何会导致无限递归的错误。我想用一种能清楚表达我意图的方式来编写我的测试。请参阅我的编辑,这解释了为什么seq
在这里不合适。好吧,f
返回一个Int
,所以WHNF和NF是相同的,对吗?但在一般情况下,你肯定是对的。你是对的,这在一般情况下是不可判定的,但是有很多方法可以证明许多函数的终止性。许多定理证明者和软件验证系统都必须这样做。对于函数式语言,一个常见的想法是在输入项上定义一个定义良好的顺序,然后通过归纳显示递归调用的参数按该顺序减少。然后,函数必须终止。当然,这些系统并不适用于所有函数,但它的工作频率足够高。是的,如果您只返回Int
,那么您不必担心seq
vsdeepseq
。是的,问题恰恰是我无法表达任何关于f
输出的合理不变量,这实际上是蒙特卡罗计算的结果。