嘗試
{-# LANGUAGE GADTs, ScopedTypeVariables #-}
import Test.QuickCheck hiding (Gen)
class Gen a where
next :: a -> a
prev :: a -> a
np_prop :: SomeGen -> Bool
np_prop (SomeGen a) = prev (next a) == a
main :: IO()
main = quickCheck np_prop
instance Gen Bool where
next True = False
next False = True
prev True = False
prev False = True
instance Gen Int where
next = (+ 1)
prev = subtract 1
data SomeGen where
SomeGen :: (Show a, Eq a, Arbitrary a, Gen a) => a -> SomeGen
instance Show SomeGen where
showsPrec p (SomeGen a) = showsPrec p a
show (SomeGen a) = show a
instance Arbitrary SomeGen where
arbitrary = do
GenDict (Proxy :: Proxy a) <- arbitrary
a :: a <- arbitrary
return $ SomeGen a
shrink (SomeGen a) =
map SomeGen $ shrink a
data GenDict where
GenDict :: (Show a, Eq a, Arbitrary a, Gen a) => Proxy a -> GenDict
instance Arbitrary GenDict where
arbitrary =
elements
[ GenDict (Proxy :: Proxy Bool)
, GenDict (Proxy :: Proxy Int)
]
data Proxy a = Proxy
類型類物化到存在性量化詞典,在其上定義一個Arbitrary
實例。然後使用此Arbitrary
字典實例爲存在量化值定義Arbitrary
的實例。
另一個例子在https://github.com/sonyandy/var/blob/4e0b12c390eb503616d53281b0fd66c0e1d0594d/tests/properties.hs#L217處給出。
如果您願意使用ConstraintKinds
,這可以進一步推廣(並減少樣板文件)。以下僅定義一次。
data Some c where
Some :: (Show a, Arbitrary a, c a) => a -> Some c
instance Show (Some c) where
showsPrec p (Some a) = showsPrec p a
show (Some a) = show a
instance Arbitrary (Dict c) => Arbitrary (Some c) where
arbitrary = do
Dict (Proxy :: Proxy a) :: Dict c <- arbitrary
a :: a <- arbitrary
return $ Some a
shrink (Some a) =
map Some $ shrink a
data Dict c where
Dict :: (Show a, Arbitrary a, c a) => Proxy a -> Dict c
data Proxy a = Proxy
class (c a, d a) => (c &&# d) a
instance (c a, d a) => (c &&# d) a
對於要測試每種類型的類的Dict
一個Arbitrary
實例是必要的。
instance Arbitrary (Dict (Eq &&# Gen)) where
arbitrary =
elements
[ Dict (Proxy :: Proxy Bool)
, Dict (Proxy :: Proxy Int)
]
np_prop :: Some (Eq &&# Gen) -> Bool
np_prop (Some a) = prev (next a) == a
對於進口使用並行'SRC /'和'測試/'目錄時,你要設置'HS-來源,迪爾斯:SRC,test'在'.cabal'文件,使這兩個目錄在模塊搜索路徑中。 – hammar 2012-04-06 01:29:48
爲什麼內部不能有屬性? – alternative 2012-04-06 11:10:13
他們當然可以,只是難以得到測試,並且(以我的經驗),測試導出行爲而不是實現細節會更有用。 – So8res 2012-04-06 13:28:00