【问题标题】:How to implement the Arbitrary instance for data type like this?如何为这样的数据类型实现任意实例?
【发布时间】:2017-10-19 07:26:36
【问题描述】:

我是 Haskell 的新手,我正在尝试编写一个测试用例来证明 Semigroup 类型类的结合律。

数据类型定义如下:

newtype Combine a b = Combine {unCombine :: (a -> b)}

Semigroup 的实现如下:

instance (Semigroup b) => Semigroup (Combine a b) where 
  (Combine f) <> (Combine g) = Combine (\x -> f x <> g x)

我已经写了一个关联测试函数

assocTestFunc :: (Eq m, Semigroup m) => m -> m -> m -> Bool
assocTestFunc a b c = (a <> b) <> c == a <> (b <> c)

并且还定义了一个像这样的类型别名:

type CombineAssoc = Combine String Ordering -> Combine String Ordering -> Combine String Ordering -> Bool

所以在我的 main 函数中,我可以这样测试它:

  quickCheck (assocTestFunc :: CombineAssoc)

但是,我很难为 Combine a b 数据类型实现 Arbitrary 实例。 提前感谢您的帮助。

【问题讨论】:

    标签: haskell typeclass quickcheck


    【解决方案1】:

    您可以利用函数的预定义实例。

    instance (CoArbitrary a, Arbitrary b) => Arbitrary(Combine a b) where
       arbitrary = Combine <$> arbitrary
    

    【讨论】:

    • 附加说明:Combine 要么需要 Show 实例,要么必须与 Blind 一起使用。否则quickCheck (assocTestFunc :: …) 不会进行类型检查。
    • 不仅如此,还需要Eq实例。
    • 是的,你们都是对的,是否可以为这种数据类型提供 Show 实例和 Eq 实例的完整实现?谢谢!
    • @PoppinDouble 不是一般的。你将如何打印函数Integer -&gt; Bool?您可以添加一个像instance Show (Combine a b) where show _ = "&lt;&lt;fun&gt;&gt;" 这样的虚拟实例,但它不会提供太多信息。如果您更具体地了解 a,b 是什么,您可能会获得更好的结果。
    • @PoppinDouble 恐怕你不能出于同样的原因:要比较两个函数,需要对它的所有输入(可能无限多)进行评估。我建议您使用 quickcheck 仅在几个随机点上对其进行测试。 IE。而不是检查f==g,您需要检查forall (\x -&gt; f x==g x) 之类的内容。这意味着您不能为此使用漂亮的assocTestFunc。很遗憾,但我们无法避免可计算性的限制。目前我找不到更好的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-14
    • 2021-04-10
    • 2021-09-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多