2013-05-08 12 views
33

Mam proste definicji typu:Jak wygenerować dowolne instancje typu prostego dla QuickCheck

data Cell = Cell { 
    x  :: Int, 
    y  :: Int 
    } deriving (Show) 

Nie mogę korzystać Cell jako wejście do nieruchomości QuickCheck, przypuszczalnie dlatego QuickCheck nie wie, w jaki sposób do generowania wartości Komórki.

Moje zrozumienie polega na tym, że muszę sprawić, że Cell stanie się egzemplarzem typu Arbitrary.

Jak to zrobić, na przykład, czy chciałbym wygenerować komórkę z losowymi dodatnimi wartościami dla xi y?

Odpowiedz

45

Zapisywanie instancji Arbitrary dla danego typu danych jest łatwe. Trzeba tylko zaimplementować funkcję arbitrary, która powinna zwrócić wartość Gen Cell. Najprostszym sposobem na to jest wykorzystanie istniejących Arbitrary instancji, a także zwrócić uwagę, że Gen jest monada, więc możemy użyć do -notation:

instance Arbitrary Cell where 
    arbitrary = do 
    Positive x <- arbitrary 
    Positive y <- arbitrary 
    return $ Cell x y 

Alternatywnie, generatory często może być napisany elegancko za pomocą operatorów z Control.Applicative :

instance Arbitrary Cell where 
    arbitrary = Cell <$> pos <*> pos 
    where pos = getPositive <$> arbitrary -- getPositive requires QC >= 2.5 

Tutaj, ja również wykorzystanie Positive modyfikator z Test.QuickCheck.Modifiers aby upewnić się, że mamy tylko generować dodatnie liczby całkowite.

Aby napisać bardziej złożone generatory, spójrz na różne generatory od Test.QuickCheck.Gen.

+2

To gdzie ja * naprawdę * lubią używać składni zamiast aplikacyjnych. –

+3

Należy również rozważyć napisanie implementacji dla 'shrink'. Może mniej ważne, ale w niektórych przypadkach oszczędza tyle wysiłku. –

15

Można wygenerować instancję Arbitrary robi to samo, używając TemplateHaskell i derive pakiet:

import Data.DeriveTH 

derive makeArbitrary ''Cell 
+5

Powinieneś wspomnieć, skąd pochodzi Data.DeriveTH. –

Powiązane problemy