首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >高阶类型的Haskell任意实例

高阶类型的Haskell任意实例
EN

Stack Overflow用户
提问于 2015-11-11 01:22:34
回答 1查看 311关注 0票数 3

我有这个类型,它是SemiGroup的一个实例。我想编写一个quickCheck方法来确保它是正确的。如何创建这种类型的任意实例?

代码语言:javascript
复制
newtype Combine a b =
  Combine { unCombine :: a -> b }

instance Semigroup b => Semigroup (Combine a b) where
  x <> y = Combine $ \n -> unCombine x n <> unCombine y n

instance (Q.Arbitrary a, Num a) => Q.Arbitrary (Combine a b) where
  arbitrary = do
    a <- Q.arbitrary
    return $ Combine (\n -> Sum(n+1)) a
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-11-11 01:40:18

最小的解决方法是打开FlexibleInstances并编写:

代码语言:javascript
复制
instance (Q.Arbitrary a, Num a) => Q.Arbitrary (Combine a (Sum a)) where
  arbitrary = do
    a <- Q.arbitrary :: Q.Gen ()
    return $ Combine (\n -> Sum(n+1))

但是,这有点令人不满意:我观察到a完全未使用(因此必须手动给出一个类型签名!),而且函数的分布有点乏味,因为它以1的概率返回函数(+1) (直到newtype包装)。(也许您想要return $ Combine (\n -> Sum (n+a))?但是即使这样,你可以用这种方式生成的函数类也有点无聊。我不知道你到底是什么意思,我也不会花很长时间进行投机。)

如果您想要正确地做它,您应该为每个输入产生一个随机输出。这对于universe包非常方便:

代码语言:javascript
复制
import Data.Universe
import Data.Universe.Instances.Reverse
instance (Ord a, Finite a, Q.Arbitrary b) => Q.Arbitrary (Combine a b) where
  arbitrary = Combine <$> sequenceA (const Q.arbitrary)

作为一个附带的好处,这不需要任何扩展。但是,您应该小心地选择具有小域的输入类型-- Combine Bool (Sum Int)应该很好,甚至可以是Combine Word8 (Sum Word8),但是如果您试图在类似Combine Int (Sum Int)的类型上测试一个属性,您将感到遗憾!

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33642741

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档