Let’s say I have the following type:
import Test.QuickCheck
import GHC.TypeLits
import Data.Kind
data Vect :: Nat -> Type -> Type where
VNil :: Vect 0 a
VCons :: a -> Vect n a -> Vect (n + 1) a
I want to be able to write some QuickChecks about my values, so I want to write an Arbitrary
instance.
sizedVect :: Int -> Gen a -> Gen (Vect n a)
sizedVect 0 _ = pure VNil
sizedVect n g = VCons <$> g <*> sizedVect (n - 1) g
instance Arbitrary (Vect n a) where
arbitrary :: Gen (Vect n a)
arbitrary = sized sizedVect
But it doesn’t work because, e.g, VNil
does not have the type forall n . Vect n a
, but Vect 0 a
.
Perhaps I should be able to write something like this:
sizedVect :: (n :: Nat) -> Gen a -> Gen (Vect (n :: Nat) a)
arbitrary :: Gen (n :: Nat, Vect (n :: Nat) a)
This is like a Sigma type, but it is not clear to me how to write this type in Haskell syntax (and then how to write the QuickCheck tests)