То, на чем я ехал, - это то, что у вас смешанные шрифты. А именно, 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
).