[英]Why does quickcheck pass for these two different functions Haskell?
我有兩個功能。 他們是:
f1 [] = []
f1 (x:xs) = if contains x xs then f1 xs else x:f1 xs
和
f6 xs = f1 (rev xs)
除了空列表和任何具有一個元素的列表之外,這兩個函數返回相同的列表是沒有意義的,但是在此 function 上運行快速檢查時:
prop_sort6 xs = (f1 xs == f6 xs) == True
所有的測試都通過了。 為什么會這樣?
編輯:
例如這樣做: (f1 [1,2,3] == f6 [1, 2, 3])
顯然會導致 False,但 quickcheck 仍然通過。
我們可以使用verboseCheck
而不是quickCheck
來做一些調查。
*Main Test.QuickCheck> verboseCheck prop_sort6
Passed:
[]
Passed:
[]
Passed:
[(),()]
Passed:
[(),()]
Passed:
[(),(),(),()]
... (you get the picture) ...
quickCheck
(和verboseCheck
,同理)有簽名
quickCheck :: Testable prop => prop -> IO ()
現在,我們可以沿着兔子洞往下看,看看Testable
是什么,但最重要的是,無論prop
是什么,它在運行時都必須是單態的。 也就是說,它不能有任何討厭的揮之不去的類型變量。 現在, prop_sort6
的類型被推斷為
prop_sort6 :: Eq a => [a] -> Bool
所以我們需要一個好的具體a
滿足Eq
。 對於大多數類型類,這將是一個模棱兩可的類型錯誤。 如果我們寫了以下內容,
class Foo a
myProp :: Foo a => a -> Bool
myProp _ = True
然后quickCheck myProp
產生
<interactive>:29:1: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘quickCheck’
prevents the constraint ‘(Arbitrary a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance (Arbitrary a, Arbitrary b) => Arbitrary (Either a b)
-- Defined in ‘Test.QuickCheck.Arbitrary’
instance Arbitrary Ordering
-- Defined in ‘Test.QuickCheck.Arbitrary’
instance Arbitrary Integer
-- Defined in ‘Test.QuickCheck.Arbitrary’
...plus 19 others
...plus 61 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the expression: quickCheck myProp
In an equation for ‘it’: it = quickCheck myProp
<interactive>:29:12: error:
• No instance for (Foo a0) arising from a use of ‘myProp’
• In the first argument of ‘quickCheck’, namely ‘myProp’
In the expression: quickCheck myProp
In an equation for ‘it’: it = quickCheck myProp
但是, Eq
是特殊的。 在 GHCi 中(並且僅在 GHCi 中), Eq
具有類型默認規則,因此,在沒有任何附加信息的情況下, Eq a
將被假定為Eq ()
(單位類型)。 這僅在 GHCi 中是正確的。 如果我們創建一個調用quickCheck
的main
function ,這是一個模棱兩可的類型錯誤。 但是,在 GHCi 中,它默認為()
。
現在,當然, ()
只有一個實例,所以我們只用()
列表一遍又一遍地測試 function,並且由於您的兩個函數將始終生成相同長度的列表,因此測試通過了。 您可能想在Int
上運行它。
*Main Test.QuickCheck> quickCheck (prop_sort6 :: [Int] -> Bool)
*** Failed! Falsified (after 5 tests and 1 shrink):
[0,1]
請注意,編譯器標志-Wtype-defaults
(由-Wall
啟用)將警告您有關類型默認的情況,並讓您知道有問題。 使用-Wtype-defaults
活動:
*Main Test.QuickCheck> quickCheck prop_sort6
<interactive>:11:1: warning: [-Wtype-defaults]
• Defaulting the following constraints to type ‘()’
(Arbitrary a0)
arising from a use of ‘quickCheck’ at <interactive>:11:1-21
(Show a0)
arising from a use of ‘quickCheck’ at <interactive>:11:1-21
(Eq a0)
arising from a use of ‘prop_sort6’ at <interactive>:11:12-21
• In the first argument of ‘GHC.GHCi.ghciStepIO ::
forall a. IO a -> IO a’, namely
‘(quickCheck prop_sort6)’
In a stmt of an interactive GHCi command:
it <- GHC.GHCi.ghciStepIO :: forall a. IO a -> IO a
(quickCheck prop_sort6)
+++ OK, passed 100 tests.
指定您的 function 應在例如整數列表上進行測試:
prop_sort6 :: [Int] -> Bool
prop_sort6 xs = (f1 xs == f6 xs) == True
如果您不指定類型,QuickCheck 會將[a]
填寫為[()]
並且[(), (), (), (), (), ...]
不會在您的案例中發現任何錯誤.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.