[英]QuickCheck tests for dependent types
我正在編寫依賴類型的Vector
和Matrix
數據類型。
data Vector n e where
EmptyVector :: Vector Zero e
(:>) :: e -> Vector n e -> Vector (Succ n) e
deriving instance Eq e => Eq (Vector n e)
infixr :>
data Matrix r c e where
EmptyMatrix :: Matrix Zero c e
(:/) :: Vector c e -> Matrix r c e -> Matrix (Succ r) c e
deriving instance Eq e => Eq (Matrix r c e)
infixr :/
它們取決於自然數,也取決於類型。
data Natural where
Zero :: Natural
Succ :: Natural -> Natural
我編寫了一個函數來計算矩陣中的列數。
columns :: Matrix r c e -> Int
columns m = Fold.foldr (\_ n -> 1 + n) 0 $ getRow 0 m
getRow :: Int -> Matrix r c e -> Vector c e
getRow 0 (v :/ _) = v
getRow i (_ :/ m) = getRow (i - 1) m
getRow _ EmptyMatrix = error "Cannot getRow from EmptyMatrix."
我現在想使用QuickCheck測試columns
函數。
為此,我必須將Matrix
和Vector
聲明為QuickCheck提供的Arbitrary
類型類的實例。
但是,我不知道如何做到這一點。
我的數據是否依賴於類型的事實會影響我編寫這些實例的方式嗎?
如何生成任意長度的矩陣,確保它們與定義匹配(例如(Succ(Succ r))將有兩行)?
您可以編寫在編譯時已知的特定長度的實例:
instance Arbitrary (Vector Zero e) where
arbitrary = return EmptyVector
instance (Arbitrary e, Arbitrary (Vector n e))
=> Arbitrary (Vector (Succ n) e) where
arbitrary = do
e <- arbitrary
es <- arbitrary
return (e :> es)
除非你想為你想要嘗試的每個長度寫一個表達式(或者讓template-haskell生成那些表達式),否則上面的實例本身並不是很有用。 讓Int
決定類型n
應該是什么的一種方法是在存在主義中隱藏n
:
data BoxM e where
BoxM :: Arbitrary (Vector c e) => Matrix r c e -> BoxM e
data Box e where Box :: Arbitrary (Vector c e) => Vector c e -> Box e
addRow :: Gen e -> BoxM e -> Gen (BoxM e)
addRow mkE (BoxM es) = do
e <- mkE
return $ BoxM (e :/ es)
firstRow :: Arbitrary a => [a] -> BoxM a
firstRow es = case foldr (\e (Box es) -> Box (e :> es)) (Box EmptyVector) es of
Box v -> BoxM (v :/ EmptyMatrix)
使用addRow和firstRow,編寫mkBoxM :: Int -> Int -> Gen (BoxM Int)
應該非常簡單,然后使用它:
forAll (choose (0,3)) $ \n -> forAll (choose (0,3)) $ \m -> do
BoxM matrix <- mkBoxM n m
return $ columns matrix == m -- or whatever actually makes sense
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.