2009-12-01 11 views
5

Próbuję napisać prop, który zmienia Sudoku, a następnie sprawdza, czy jest on nadal ważny.Jak używać 'oneof' w quickCheck (Haskell)

Jednak nie jestem pewien, jak poprawnie używać funkcji "oneof". Czy możesz mi podać jakieś wskazówki?

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)] 

Oto kilka informacji ...

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] 

Mam struggeled z tym rekwizytem w ciągu 3 godzin teraz, więc wszelkie pomysły są mile widziane!

+0

Cóż, jaki jest typ "aktualizacji"?Jak myślisz, czym będą typy "aCandidate" i "aBlank"? –

+0

Edytowałem post, czy mógłbyś jeszcze raz spojrzeć? – Mickel

+0

Teraz sprawdź, jaki jest typ '[return x | x <- (blanks su)] 'a zatem z' aBlank'. –

Odpowiedz

5

Co Jechałem na to, że masz typu mix-up. Mianowicie aBlank nie jest Pos, ale Gen Pos, więc nie ma sensu! W rzeczywistości to, co chcesz, to sposób na wygenerowanie nowego sudoku z początkowym sudoku; Innymi słowy funkcja

similarSudoku :: Sudoku -> Gen Sudoku 

Teraz możemy napisać:

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) 

lub jeszcze prościej:

similarSudoku su = liftM2 (update su) (elements (blanks su)) (elements (candidates su aBlank)) 

a właściwość wygląda

prop_similar :: Sudoku -> Gen Bool 
prop_similar su = do newSu <- similarSudoku su 
        return (isSudoku newSu && isOkay newSu) 

Ponieważ nie są instancje

Testable Bool 
Testable prop => Testable (Gen prop) 
(Arbitrary a, Show a, Testable prop) => Testable (a -> prop) 

Sudoku -> Gen Bool jest Testable jak również (przy założeniu instance Arbitrary Sudoku).

+0

Również nie działa, ale było bardzo pomocne, więc przyjmuję to jako odpowiedź. – Mickel

2

Na moim blogu napisałem test simple craps simulator z testami QuickCheck, które używają oneof do generowania interesujących rolek.

że mamy super Simple Sudoku pojedynczego rzędu:

module Main where 
import Control.Monad 
import Data.List 
import Test.QuickCheck 
import Debug.Trace 

type Pos = Int 
data Sudoku = Sudoku [Char] deriving (Show) 

No super prosty Sudoku powinny były powtarzane wartości:

prop_noRepeats :: Sudoku -> Bool 
prop_noRepeats [email protected](Sudoku xs) = 
    trace (show s) $ all ((==1) . length) $ 
        filter ((/='.') . head) $ 
        group $ sort xs 

może wygenerować Super Simple Sudoku z

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 jest tam, aby pokazać losowo wygenerowanego dzika 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

wydaje się, że aBlank :: Gen Pos która nie odpowiada sposób, w jaki jest używany jako argument candidates :: Sudoku -> Pos -> [Int].

Przeglądałem przez here, aby znaleźć sposób przekonwertowania Gen a na a, który pozwoliłby ci na użycie go z kandydatami. Najlepsze, co mogłem zobaczyć, to funkcja generate.

Powiedz mi, czy ja czegoś brakuje ...

+0

No tak. Nie musisz "konwertować" Gen a "na" a "; zamiast tego chcesz "podnieść" "kandydatów". –

+0

I oczywiście inne potrzebne funkcje. –

+0

ma sens. Jedną z rozwiązań jest monadyczne wyjście. – barkmadley

Powiązane problemy