2013-05-08 11 views
33

Tôi có một định nghĩa kiểu đơn giản:Làm thế nào để tạo ra các trường hợp tùy tiện của một kiểu đơn giản cho QuickCheck

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

tôi không thể sử dụng Cell như một đầu vào cho một tài sản QuickCheck, có lẽ vì QuickCheck không biết làm thế nào để tạo ra các giá trị Cell.

Sự hiểu biết của tôi là tôi cần tạo Cell làm phiên bản của kiểu chữ là Arbitrary.

Làm cách nào để thực hiện điều đó, ví dụ: nếu tôi muốn Tạo ô bằng các giá trị dương cho x và y?

Trả lời

45

Viết thể hiện Arbitrary cho loại dữ liệu của bạn thật dễ dàng. Bạn chỉ cần triển khai hàm arbitrary, hàm này sẽ trả về một số Gen Cell. Cách đơn giản nhất để làm điều này là để tận dụng Arbitrary trường hiện có và cũng lưu ý rằng Gen là một đơn nguyên, vì vậy chúng tôi có thể sử dụng do -notation:

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

Ngoài ra, máy phát điện thường có thể được viết thanh lịch sử dụng khai thác từ Control.Applicative :

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

ở đây, tôi cũng đã thực hiện việc sử dụng Positive modifier từ Test.QuickCheck.Modifiers để đảm bảo rằng chúng tôi chỉ tạo nguyên dương.

Để viết các trình tạo phức tạp hơn, hãy xem các trình tạo khác nhau từ Test.QuickCheck.Gen.

+2

Đây là nơi tôi sẽ * thực sự * muốn sử dụng cú pháp applicative để thay thế. –

+3

Ngoài ra, hãy xem xét việc viết một thực hiện cho 'thu nhỏ'. Ít quan trọng ở đây, có lẽ, nhưng tiết kiệm rất nhiều nỗ lực cho một số trường hợp. –

15

Bạn có thể tạo một Arbitrary dụ làm tương tự sử dụng TemplateHaskell và derive gói:

import Data.DeriveTH 

derive makeArbitrary ''Cell 
+5

Bạn nên đề cập đến nơi Data.DeriveTH đến từ. –