使用Hedgehog(或任何其他基于属性的测试框架)生成随机GADT的最安全方法

She*_*rsh 7 haskell type-safety gadt property-based-testing haskell-hedgehog

我有像这样的GADT:

data TType a where
    TInt  :: TType Int
    TBool :: TType Bool
Run Code Online (Sandbox Code Playgroud)

我想要一个像这样的功能:

genTType :: Gen (TType a)
Run Code Online (Sandbox Code Playgroud)

哪个可以生成TType类型的随机构造函数.我可以通过创建存在的合格数据类型来实现这一点

data AnyType = forall a . MkAnyType (TType a)
Run Code Online (Sandbox Code Playgroud)

然后生成随机数01(包括)并AnyType根据整数值创建.像这样:

intToAnyType :: Int -> AnyType
intToAnyType 0 = MkAnyType TInt
intToAnyType 1 = MkAnyType TBool
intToAnyType _ = error "Impossible happened"
Run Code Online (Sandbox Code Playgroud)

但这种方法对我来说有几个缺点:

  1. 没有外部类型安全.如果我向TType数据类型添加另一个构造函数,我可能忘记修复测试,编译器不会警告我这一点.
  2. 编译器无法阻止我写作intToAnyType 1 = MkAnyType TInt.
  3. 我不喜欢这个error.Int类型太宽泛了我.让这种模式匹配详尽无遗是件好事.

我可以在Haskell中做些什么来消除尽可能多的缺点?最好使用此模块的发电机:

Li-*_*Xia 4

使用 Template Haskell生成genTType可能是自动维护生成器的最佳选择,因为 GADT 没有通用编程支持。

对于最后一点,不要生成整数然后将其映射到值,而是使用oneofelement

 element [MkAnyType TInt, MkAnyType TBool]
Run Code Online (Sandbox Code Playgroud)