Haskell Test.QuickCheck未正确生成随机值

Haskell Test.QuickCheck未正确生成随机值,haskell,Haskell,我正在使用Test.QuickCheck生成随机数独游戏 data Sudoku = Sudoku { getSudoku :: [[Maybe Int]] } deriving (Show, Eq) rows :: Sudoku -> [[Maybe Int]] rows (Sudoku rs) = rs --B1 printSudoku :: Sudoku -> IO () printSudoku s = do putStrLn . unlines . map (ma

我正在使用Test.QuickCheck生成随机数独游戏

data Sudoku = Sudoku { getSudoku :: [[Maybe Int]] } deriving (Show, Eq)

rows :: Sudoku -> [[Maybe Int]]
rows (Sudoku rs) = rs

--B1
printSudoku :: Sudoku -> IO ()
printSudoku s = do
    putStrLn . unlines . map (map (maybe '.' (head . show))) $ rows s

--C1
cell :: Gen (Maybe Int)
cell = suchThatMaybe (frequency [(90, choose (0,0)),(10, choose(1,9))]) (/=0)

--C2
instance Arbitrary Sudoku where
    arbitrary = do
        rows <- sequence [ sequence [ cell | j <- [1..9] ] | i <- [1..9] ]
        return (Sudoku rows)

--C3
prop_Sudoku :: Sudoku -> Bool
prop_Sudoku = isSudoku

checkRandomSudoku :: IO [Bool]
checkRandomSudoku = do
    s <- sample' (arbitrary :: Gen Sudoku)
    return $ map isSudoku s

这显然不是随机的。空细胞的分布最初很高,然后缓慢减少。我是否使用了错误的功能或方式?谢谢

您看到这种行为的原因是QuickCheck会尝试越来越大的测试用例。本手册章节对此进行了说明

这样的情况下,增加大小可能会使它重试生成一个与传递给它的谓词匹配的任意谓词。您可以在源代码中看到这一点。有趣的代码是:

try _ 0 = return Nothing
try k n = do x <- resize (2*k+n) gen
             if p x then return (Just x) else try (k+1) (n-1)

作为对您的方法的评论(而不是您对当前问题的描述):我怀疑这不是一个好主意。生成正确的数独谜题似乎是听起来很容易但实际上并不容易的事情之一,我敢打赌,一旦你解决了这个问题,你会遇到很多奇怪的问题。但是在野外已经有很多谜题了——你能用现有的语料库跳过所有的问题吗?我只是按照找到的练习。我有点同意你的看法。在我的示例中,您可以看到它甚至没有检查行/列/框中是否有重复的数字,但我仍然想了解它为什么没有像我预期的那样生成随机数。特别是频率,我会期待更多的未填写的条目,因为我有它比我看到的编号entries更多的重量。我认为它相当不直观,因为hackage上函数的描述并不表明它影响其谓词的概率。我很想知道,如果不使用调整大小,这些东西可能会被用来做什么?如果你能帮我举个例子好吗?感谢
这样的想法,可能
是为了涵盖尽可能多的不同测试用例。所以,如果您有一个很少满足的谓词,那么通过重试,它更有可能命中一个肯定的测试用例。
try _ 0 = return Nothing
try k n = do x <- resize (2*k+n) gen
             if p x then return (Just x) else try (k+1) (n-1)
>>> a <- sample' $ (resize 2 arbitrary :: Gen Sudoku)
>>> sequence $ map printSudoku a
.....8.5.
.......4.
.........
4..25...5
......9..
....5....
........7
.....7...
...4.....

...5.....
.......4.
...6...6.
..14.....
...7...7.
....2....
.....6...
...4..572
.4.....6.

..6..8...
..4......
.........
......9..
839......
67..4....
.5.......
....5....
........3

4...1....
7..9.39..
....6....
...4.1...
.........
.........
..9....6.
.2.9...84
.....8...

.64......
..3.44...
4.......4
....1..8.
.9.......
34.......
.....6...
18.2..593
.4.7.....

.........
...8..6..
.2......5
...5.....
.2.......
........6
.3....13.
8.1.2..85
....5....

..7......
..67...5.
..6......
27....1.9
.9.......
78.....7.
......34.
.......2.
..81...81

3.1......
.........
.....6...
.........
.16.71...
.........
.2.......
.........
.....9.1.

..65..6.9
........5
..1.4....
....86...
.2..2..2.
.....9...
..6......
.........
...7..855

.......94
...14..8.
.....4...
...3....9
.........
.....5...
.5.......
45.....8.
..48.....

4........
......3..
5......4.
.4..6..2.
..3......
.........
..9......
6..9.....
....7....