Trong khi nó sẽ giúp đỡ nếu bạn đã thực hiện gen
, tôi đoán rằng nó đi một cái gì đó như thế này:
gen :: a -> ([a] -> [a]) -> ([a] -> Bool) -> a
gen init next stop = loop [init]
where
loop xs | stop xs = head xs
| otherwise = loop (next xs)
Thuộc tính bạn muốn kiểm tra là next
không bao giờ được cung cấp một danh sách trống . Một trở ngại để kiểm tra điều này là bạn muốn kiểm tra bất biến vòng lặp bên trong bên trong gen
, vì vậy điều này cần phải có sẵn từ bên ngoài. Chúng ta hãy sửa đổi gen
trở về thông tin này:
genWitness :: a -> ([a] -> [a]) -> ([a] -> Bool) -> (a,[[a]])
genWitness init next stop = loop [init]
where
loop xs | stop xs = (head xs,[xs])
| otherwise = second (xs:) (loop (next xs))
Chúng tôi sử dụng second
từ Control.Arrow. Bản gốc gen
có thể dễ dàng xác định theo genWitness:
gen' :: a -> ([a] -> [a]) -> ([a] -> Bool) -> a
gen' init next stop = fst (genWitness init next stop)
Nhờ đánh giá lười biếng này sẽ không cho chúng ta nhiều chi phí. Quay lại tài sản! Để bật hiển thị các hàm được tạo từ QuickCheck, , chúng tôi sử dụng mô-đun Test.QuickCheck.Function. Mặc dù không cần thiết ở đây, thói quen tốt là để định hình bất động sản: chúng tôi sử dụng danh sách Int
s thay vì cho phép giới hạn đơn cấu hình biến chúng thành danh sách đơn vị. Bây giờ chúng ta nêu tài sản:
prop_gen :: Int -> (Fun [Int] [Int]) -> (Fun [Int] Bool) -> Bool
prop_gen init (Fun _ next) (Fun _ stop) =
let trace = snd (genWitness init next stop)
in all (not . null) trace
Chúng ta hãy thử chạy nó với QuickCheck:
ghci> quickCheck prop_gen
Something dường như vòng lặp ... Có tất nhiên: gen
vòng nếu stop
trên danh sách từ next
không bao giờ là True
!Hãy để chúng tôi thay vì cố gắng nhìn vào tiền tố hữu hạn của các dấu vết đầu vào thay vì:
prop_gen_prefix :: Int -> (Fun [Int] [Int]) -> (Fun [Int] Bool) -> Int -> Bool
prop_gen_prefix init (Fun _ next) (Fun _ stop) prefix_length =
let trace = snd (genWitness init next stop)
in all (not . null) (take prefix_length trace)
Chúng tôi hiện nhanh chóng có được aa phản ví dụ:
385
{_->[]}
{_->False}
2
Chức năng thứ hai là lập luận next
, và nếu nó trả về danh sách trống, thì vòng lặp trong gen
sẽ cung cấp cho next
danh sách trống.
Tôi hy vọng điều này sẽ trả lời câu hỏi này và nó cung cấp cho bạn một số thông tin chi tiết về cách kiểm tra các hàm bậc cao hơn bằng QuickCheck.
Đây là thuộc tính liên quan: "Đối với bất kỳ đầu vào không trống nào,' tiếp theo' sẽ tạo ra kết quả không trống ". Bạn có thể quan tâm đến việc thử nghiệm thay vào đó, hoặc thêm vào, thuộc tính bạn đề cập. –
@JohnL Thật vậy! Nhưng đó là tài sản của 'next', không phải' gen', và 'next' là thứ tự đầu tiên, vì vậy tôi biết cách kiểm tra nó. –