我有一個環型類看起來像這樣可變數目:測試類型類與快速檢查,參數
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 ...
爲了測試這種情況下,我有以下快速檢查測試:
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
我不確定如何運行這些測試用例爲我所有的類的實例。我找到了解決辦法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 2014-10-20 14:59:07
我不認爲你可以自動做到這一點。此外,我認爲這甚至不可取。如果您的模塊的用戶將您的測試函數導入到她定義自定義實例的模塊中,該函數是否應該自動測試該實例? – DanielM 2014-10-20 17:46:37