sda*_*das 6 haskell quickcheck
我正在编写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 :/
Run Code Online (Sandbox Code Playgroud)
它们取决于自然数,也取决于类型.
data Natural where
Zero :: Natural
Succ :: Natural -> Natural
Run Code Online (Sandbox Code Playgroud)
我编写了一个函数来计算矩阵中的列数.
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."
Run Code Online (Sandbox Code Playgroud)
我现在想columns使用QuickCheck 测试该功能.
为此,我必须声明Matrix并Vector作为ArbitraryQuickCheck提供的类型类的实例.
但是,我不知道如何做到这一点.
我的数据是否依赖于类型的事实会影响我编写这些实例的方式吗?
如何生成任意长度的矩阵,确保它们与定义匹配(例如(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)
Run Code Online (Sandbox Code Playgroud)
除非你想为你想要尝试的每个长度写一个表达式(或者让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)
Run Code Online (Sandbox Code Playgroud)
使用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
Run Code Online (Sandbox Code Playgroud)