2009-12-01 8 views
5

私は数独を変えてそれがまだ有効であるかどうかを調べるために小道具を書こうとしています。quickcheck(Haskell)で 'oneof'を使用する方法

しかし、 "oneof"関数を正しく使用する方法がわかりません。あなたは私にいくつかのヒントをくれますか?ここで

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ているので、任意のアイデアを歓迎します!

+0

「更新」の種類は何ですか?そして、「aCandidate」と「aBlank」の種類はどうなると思いますか? –

+0

投稿を編集しました。どうぞご覧ください。 – Mickel

+0

ここで、 '[return x | x < - (blanks su)] 'となり、' aBlank'の結果となります。 –

答えて

5

私がで運転していたことは、あなたがタイプミックスアップを持っているということです。つまりaBlankPosではありませんが、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 Boolinstance Arbitrary Sudokuを想定)もTestableあります。

+0

本当にうまくいきませんでしたが、非常に参考になりましたので、私は答えとして受け入れます。 – Mickel

2

私のブログでは、oneofを使用して面白いロールを生成するQuickCheckテストでsimple craps simulatorを書きました。

は、我々は、単一の行の超簡単な数独を持って言う:

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 [email protected](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は、ランダムに生成されたイノシシDSは:

*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. 
1

それはcandidates :: Sudoku -> Pos -> [Int]の引数として使用されている方法と一致しないことaBlank :: Gen Posです。

私はGen aaに変換する方法を見つけるためにhereを探していましたが、候補者と一緒に使うことができます。最高の私が見ることができるgenerate機能です。

は、私は何かが欠けていた場合を教えてください...

+0

まあ、はい。あなたは 'Gen a'を' a'に変換することは望んでいません。あなたは代わりに「候補者」を「持ち上げたい」。 –

+0

もちろん、他の機能も含まれています。 –

+0

が理にかなっています。行くモナディックは解決策です。 – barkmadley

関連する問題