gpt4 book ai didi

scala - 为什么 scalacheck 中需要 Arbitraries?

转载 作者:行者123 更新时间:2023-12-02 21:04:30 25 4
gpt4 key购买 nike

我想知道为什么需要任意,因为自动化属性测试需要属性定义,例如

val prop = forAll(v: T => check that property holds for v)

和值 v 生成器。用户指南说您可以为自定义类型创建自定义生成器(以树生成器为例)。然而,它并没有解释为什么除此之外还需要任意的。

这是一份手册

implicit lazy val arbBool: Arbitrary[Boolean] = Arbitrary(oneOf(true, false))

To get support for your own type T you need to define an implicit def or val of type Arbitrary[T]. Use the factory method Arbitrary(...) to create the Arbitrary instance. This method takes one parameter of type Gen[T] and returns an instance of Arbitrary[T].

它清楚地表明我们需要在 Gen 之上的任意性。尽管如此,任意性的理由并不令人满意

The arbitrary generator is the generator used by ScalaCheck when it generates values for property parameters.

IMO,要使用生成器,您需要导入它们而不是将它们包装到任意生成器中!否则,有人可能会争辩说我们需要将任意值包装到其他东西中以使它们可用(等等无限地包装包装器)。

您还可以解释如何任意[Int]将参数类型转换为生成器。很好奇,我觉得这些都是相关的问题。

最佳答案

forAll { v: T => ... } 是在 Scala 的帮助下实现的隐式。这意味着 T 类型的生成器是隐式找到的,而不是由调用者显式指定的。

Scala 隐式很方便,但如果您不确定当前范围内的隐式值或转换,它们也可能会很麻烦。通过使用特定类型(Arbitrary)进行隐式查找,ScalaCheck 尝试限制使用隐式的负面影响(这种使用也使其类似于我们熟悉的 Haskell 类型类对于某些用户)。

所以,您完全正确,实际上并不需要Arbitrary。通过隐式 Gen[T] 值可以实现相同的效果,但可能会带来更多隐式范围界定困惑。

作为最终用户,您应该将 Arbitrary[T] 视为 T 类型的默认生成器。您可以(通过范围界定)定义和使用多个 Arbitrary[T] 实例,但我不推荐这样做。相反,只需跳过Arbitrary并明确指定您的生成器:

val myGen1: Gen[T] = ...val mygen2: Gen[T] = ...val prop1 = forAll(myGen1) { t => ... }val prop2 = forAll(myGen2) { t => ... }
<小时/>

任意 [Int] 的工作方式与 forAll { n: Int => ... } 类似,它只是查找隐式 Arbitrary[Int] 实例并使用它的生成器。实现很简单:

def arbitrary[T](implicit a: Arbitrary[T]): Gen[T] = a.arbitrary

Arbitrary 的实现在这里也可能会有所帮助:

sealed abstract class Arbitrary[T] {  val arbitrary: Gen[T]}

关于scala - 为什么 scalacheck 中需要 Arbitraries?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31111106/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com