quickCheck(ハスケル)に「oneofの」を使用する方法
-
11-09-2019 - |
質問
私は数独を変更して、それはまだ有効ですかどうかを確認する小道具を記述しようとしています。
しかし、私はきちんと「oneofの」-functionを使用するかどうかはわかりません。あなたは私にいくつかのヒントを与えることができ、してください?
prop_candidates :: Sudoku -> Bool
prop_candidates su = isSudoku newSu && isOkay newSu
where
newSu = update su aBlank aCandidate
aCandidate = oneof [return x | x <- candidates su aBlank]
aBlank = oneof [return x | x <- (blanks su)]
ここではいくつかの詳細情報です...
type Pos = (Int, Int)
update :: Sudoku -> Pos -> Maybe Int -> Sudoku
blanks :: Sudoku -> [Pos]
candidates :: Sudoku -> Pos -> [Int]
[return x | x <- (blanks example)] :: (Monad m) => [m Pos]
私は今、3時間この小道具でstruggeledているので、任意のアイデアは大歓迎です!
解決
私は何で運転していたことは、あなたがタイプミックスアップを持っているということです。つまり、aBlank
はPos
が、Gen Pos
ないので、update su aBlank aCandidate
は意味がありません!実際には、何が欲しいのは最初の数独与えられた新しい数独を生成する方法です。言い換えれば、関数
similarSudoku :: Sudoku -> Gen Sudoku
今、私たちはそれを書くことができます:
similarSudoku su = do aBlank <- elements (blanks su)
-- simpler than oneOf [return x | x <- blanks su]
aCandidate <- elements (candidates su aBlank)
return (update su aBlank aCandidate)
あるいはさらに簡単ます:
similarSudoku su = liftM2 (update su) (elements (blanks su)) (elements (candidates su aBlank))
とプロパティは、
のようになります。prop_similar :: Sudoku -> Gen Bool
prop_similar su = do newSu <- similarSudoku su
return (isSudoku newSu && isOkay newSu)
のインスタンスが存在するので
Testable Bool
Testable prop => Testable (Gen prop)
(Arbitrary a, Show a, Testable prop) => Testable (a -> prop)
Sudoku -> Gen Bool
はTestable
も同様である(instance Arbitrary Sudoku
を仮定)。
他のヒント
私のブログでは、私はシンプルクラップスシミュレータを書きました興味深いのロールを生成するために、 oneof
を使用QuickCheckをテストします。
私たちは、単一の行の超簡単な数独があるとします:
module Main where
import Control.Monad
import Data.List
import Test.QuickCheck
import Debug.Trace
type Pos = Int
data Sudoku = Sudoku [Char] deriving (Show)
何超簡単な数独は、値を繰り返さなかったはずです
prop_noRepeats :: Sudoku -> Bool
prop_noRepeats s@(Sudoku xs) =
trace (show s) $ all ((==1) . length) $
filter ((/='.') . head) $
group $ sort xs
は、
で超簡単な数独を生成することがありますinstance Arbitrary Sudoku where
arbitrary = sized board :: Gen Sudoku
where board :: Int -> Gen Sudoku
board 0 = Sudoku `liftM` shuffle values
board n | n > 6 = resize 6 arbitrary
| otherwise =
do xs <- shuffle values
let removed = take n xs
dots = take n $ repeat '.'
remain = values \\ removed
ys <- shuffle $ dots ++ remain
return $ Sudoku ys
values = ['1' .. '9']
shuffle :: (Eq a) => [a] -> Gen [a]
shuffle [] = return []
shuffle xs = do x <- oneof $ map return xs
ys <- shuffle $ delete x xs
return (x:ys)
trace
は、ランダムに生成されたボードを示すことがあります:
*Main> quickCheck prop_noRepeats
Sudoku "629387451"
Sudoku "91.235786"
Sudoku "1423.6.95"
Sudoku "613.4..87"
Sudoku "6..5..894"
Sudoku "7.2..49.."
Sudoku "24....1.."
[...]
+++ OK, passed 100 tests.
それはaBlank :: Gen Pos
の引数として使用されている方法と一致しないことcandidates :: Sudoku -> Pos -> [Int]
ようです。
私はここにて探していた見つけることをあなたが候補者とそれを使用できるようになるGen a
にa
を変換する方法。私が見ることができる最高はgenerate
機能です。
私は何かが欠けていた場合を教えてください...