5

ここに簡単な関数があります。これは入力を取り、ペアIntの (場合によっては空の) リストを返します(Int, Int)。ここで、入力Intは任意のペアの 3 乗要素の合計です。

cubeDecomposition :: Int -> [(Int, Int)]
cubeDecomposition n = [(x, y) | x <- [1..m], y <- [x..m], x^3 + y^3 == n] 
  where m = truncate $ fromIntegral n ** (1/3)

-- cubeDecomposition 1729
-- [(1,12),(9,10)]

上記が真であるというプロパティをテストしたい。各要素を 3 乗し、返されたタプルのいずれかを合計すると、入力が返されます。

import Control.Arrow 

cubedElementsSumToN :: Int -> Bool
cubedElementsSumToN n = all (== n) d
    where d = map (uncurry (+) . ((^3) *** (^3))) (cubeDecomposition n)

Int実行時の考慮事項として、 QuickCheck でこれをテストするときに入力 s を特定のサイズに制限したいと思います。適切なタイプとArbitraryインスタンスを定義できます。

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

import Test.QuickCheck

newtype SmallInt = SmallInt Int
    deriving (Show, Eq, Enum, Ord, Num, Real, Integral)

instance Arbitrary SmallInt where
    arbitrary = fmap SmallInt (choose (-10000000, 10000000))

SmallIntそして、次の代わりに使用する関数とプロパティのバージョンを定義する必要があると思いますInt

cubeDecompositionQC :: SmallInt -> [(SmallInt, SmallInt)]
cubeDecompositionQC n = [(x, y) | x <- [1..m], y <- [x..m], x^3 + y^3 == n] 
  where m = truncate $ fromIntegral n ** (1/3)

cubedElementsSumToN' :: SmallInt -> Bool
cubedElementsSumToN' n = all (== n) d
    where d = map (uncurry (+) . ((^3) *** (^3))) (cubeDecompositionQC n)

-- cubeDecompositionQC 1729
-- [(SmallInt 1,SmallInt 12),(SmallInt 9,SmallInt 10)]

これは正常に機能し、標準の 100 テストは期待どおりにパスします。しかし、本当に必要なのはカスタム ジェネレーターだけである場合、新しい型、インスタンス、および関数を定義する必要はないように思われます。だから私はこれを試しました:

smallInts :: Gen Int
smallInts = choose (-10000000, 10000000)

cubedElementsSumToN'' :: Int -> Property
cubedElementsSumToN'' n = forAll smallInts $ \m -> all (== n) (d m)
    where d =   map (uncurry (+) . ((^3) *** (^3)))
              . cubeDecomposition

さて、これを最初に数回実行したところ、すべてが正常に機能し、すべてのテストに合格しました。しかし、その後の実行では、失敗が観察されました。テストサイズを大きくすると、次のものが確実に見つかります。

*** Failed! Falsifiable (after 674 tests and 1 shrink):  
0
8205379

QuickCheck から返された 0 と 8205379の2 つの縮小された入力が存在するため、ここでは少し混乱しています。また、これらの入力は予測どおりに機能します (少なくとも私の show-able プロパティでは):

*Main> cubedElementsSumToN 0
True
*Main> cubedElementsSumToN 8205379
True

Gen明らかに、私が定義したカスタムを使用するプロパティに問題があるようです。

私は何を間違えましたか?

4

1 に答える 1

4

私が書いたプロパティが明らかに間違っていることにすぐに気付きました。cubedElementsSumToN元のプロパティを使用して、これを行う適切な方法は次のとおりです。

quickCheck (forAll smallInts cubedElementsSumToN)

これは非常に自然に読めます。

于 2012-11-13T02:55:30.813 に答える