Создание списка списков Int с помощью QuickCheck

Я работаю над Real World Haskell, одним из упражнений главы 4 является реализация foldr-ориентированного версия concat. Я подумал, что это будет отличным кандидатом для тестирования с помощью QuickCheck, поскольку существует уже существующая реализация для проверки моих результатов. Однако это требует от меня определения экземпляра класса типов Arbitrary, который может генерировать произвольные [[Int]]. Пока не могу понять, как это сделать. Моя первая попытка была:

module FoldExcercises_Test
where

import Test.QuickCheck
import Test.QuickCheck.Batch

import FoldExcercises

prop_concat xs = 
    concat xs == fconcat xs
    where types = xs ::[[Int]]


options = TestOptions { no_of_tests = 200
                      , length_of_tests = 1
                      , debug_tests = True }

allChecks = [ 
              run (prop_concat)
            ]

main = do
  runTests "simple" options allChecks

Это приводит к тому, что тесты не проводятся. Глядя на различные фрагменты, я догадался, что требуется объявление экземпляра Arbitrary, и добавил

    instance Arbitrary a => Arbitrary [[a]] where
    arbitrary = sized arb' 
        where arb' n = vector n (arbitrary :: Gen a)

Это привело к тому, что ghci пожаловался, что объявление моего экземпляра недействительно и что добавление -XF flexibleInstances может решить мою проблему. Добавление директивы {-# OPTIONS_GHC -XFlexibleInstances #-} приводит к несоответствию типов и предупреждению о перекрывающихся экземплярах.

Итак, мой вопрос: что нужно, чтобы это работало? Я, очевидно, новичок в Haskell и не нахожу никаких ресурсов, которые могли бы мне помочь. Любые указатели очень ценятся.

Редактировать

Похоже, что вывод QuickCheck ввел меня в заблуждение, когда при первом тестировании fconcat определяется как

fconcat = undefined  

Собственно правильная реализация функции действительно дает ожидаемый результат. DOOP!


person Bas Bossink    schedule 06.11.2009    source источник


Ответы (1)


[[Int]] уже является экземпляром Arbitrary (поскольку Int является экземпляром Arbitrary, поэтому [a] для всех a, которые сами являются экземплярами Arbitrary). Так что проблема не в этом.

Я сам запустил ваш код (заменив import FoldExcercises на fconcat = concat), и он провел 200 тестов, как я и ожидал, поэтому я озадачен, почему он не делает этого за вас. Но вам НЕ нужно добавлять экземпляр Arbitrary.

person dave4420    schedule 06.11.2009
comment
я согласен. это отлично работало для меня в ghc 6.10.4 на OSX Leopard - person barkmadley; 07.11.2009