QuickCheck (Haskell)에서 'Oneof'를 사용하는 방법
-
11-09-2019 - |
문제
스도쿠를 바꾸는 소품을 쓰려고 노력한 다음 여전히 유효한지 확인합니다.
그러나 "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 시간 동안 투쟁 했으므로 모든 아이디어를 환영합니다!
해결책
내가 운전했던 것은 당신이 타입 믹스 업이 있다는 것입니다. 즉, aBlank
아닙니다 Pos
, 그러나 a 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
).
다른 팁
내 블로그에서 나는 a를 썼다 간단한 크랩 시뮬레이터 빠른 검사 테스트를 사용하여 사용합니다 oneof
흥미로운 롤을 생성합니다.
단일 행의 슈퍼 단순 스도쿠가 있다고 가정 해 봅시다 :
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
당신은 super-simple sudoku를 생성 할 수 있습니다
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
기능.
내가 뭔가를 놓치면 말해줘 ...