у меня есть класс типа кольца, которое выглядит следующим образом:классов типов тестирования с QuickCheck, переменное число параметров
class Ring a where
addId :: a
addInverse :: a -> a
mulId :: a
add :: a -> a -> a
mul :: a -> a -> a
Для этого класса у меня есть несколько примеров, например,
instance Ring Matrix where ...
instance Ring Integer where ...
instance Ring Modulo where ...
Для того, чтобы проверить эти примеры, я следующие QuickCheck тесты:
prop_AddId :: (Ring a, Eq a, Arbitrary a) => a -> Bool
prop_AddInv :: (Ring a, Eq a, Arbitrary a) => a -> Bool
prop_MulId :: (Ring a, Eq a, Arbitrary a) => a -> Bool
prop_AddCommutative :: (Ring a, Eq a, Arbitrary a) => a -> a -> Bool
prop_AddAssociative :: (Ring a, Eq a, Arbitrary a) => a -> a -> a -> Bool
prop_MulAssociative :: (Ring a, Eq a, Arbitrary a) => a -> a -> a -> Bool
prop_Distributive :: (Ring a, Eq a, Arbitrary a) => a -> a -> a -> Bool
Я уверен, как запустить эти testcases для всех моих экземпляров класса. Я нашел решение here , что приводит к следующему:
forallRings :: (forall a. (Ring a, Arbitrary a, Eq a) => a -> Bool) -> [IO()]
forallRings x =
[ quickCheck (x :: Matrix -> Bool)
, quickCheck (x :: Integer -> Bool)
, quickCheck (x :: Modulo -> Bool)
]
forallRings2 :: (forall a. (Ring a, Arbitrary a, Eq a) => a -> a -> Bool) -> [IO()]
forallRings2 x =
[ quickCheck (x :: Matrix -> Matrix -> Bool)
, quickCheck (x :: Integer -> Integer -> Bool)
, quickCheck (x :: Modulo -> Modulo -> Bool)
]
forallRings3 :: (forall a. (Ring a, Arbitrary a, Eq a) => a -> a -> a -> Bool) -> [IO()]
forallRings3 x =
[ quickCheck (x :: Matrix -> Matrix -> Matrix -> Bool)
, quickCheck (x :: Integer -> Integer -> Integer -> Bool)
, quickCheck (x :: Modulo -> Modulo -> Modulo -> Bool)
]
ringTests :: IO()
ringTests = sequence_ $
forallRings propAddId
++ forallRings prop_AddInv
++ forallRings prop_MulId
++ forallRings2 prop_AddCommutative
++ forallRings3 prop_AddAssociative
++ forallRings3 prop_MulAssociative
++ forallRings3 prop_Distributive
Я несколько недоволен этим решением. Я считаю, что функции forAllRingsX немного уродливы и повторяются. Причина в том, что мои тесты имеют различное количество параметров. Есть ли лучший способ (т. Е. Один с меньшим кодом котельной плиты) для проверки всех экземпляров?
Это выглядит как работа для семейств типов. У меня нет времени экспериментировать прямо сейчас, но, возможно, кто-то будет. – chi
Я не думаю, что вы можете сделать это автоматически. Более того, я думаю, что это даже не было бы желательно. Если пользователь вашего модуля должен был импортировать вашу тестовую функцию в модуль, где она определила собственный экземпляр, должна ли функция автоматически проверить этот экземпляр? – DanielM