【问题标题】:Why does this Hedgehog generator not shrink faster?为什么这个 Hedgehog 生成器不收缩得更快?
【发布时间】:2020-07-17 23:26:03
【问题描述】:

我制作了一个 Hedgehog 生成器,它通过以下方式生成任意 256 位值:

genWord256 :: Gen Word256
genWord256 = do
  bytes <- Gen.integral (Range.linear 0 31)
  let lo = 2 ^ (8 * bytes)
      hi = 2 ^ (8 * (bytes + 1))
  pred <$> Gen.integral (Range.constant lo hi)

我认为,让 size 参数确定数字中的字节数对我的应用程序很有意义。但是,评估此生成器如何缩小,并将ceiling . logBase 2 应用于此,我的问题是:

为什么刺猬决定强调其初始结果的附近?我是否以某种方式误解了“不受大小参数影响的范围”的含义? (Range.constant) 我原以为这里的任何收缩都必须有更少的位数。

λ> Gen.print genWord256
=== Outcome ===
68126922926972638
=== Shrinks ===
112                 -- 7 bits
4035711763          -- 32 bits
106639875637011     -- 47 bits
281474976710655     -- 48 bits
34204198951841647   -- 55 bits
51165560939407143   -- 56 bits
59646241933189891   -- ...
67994412286444783   -- ...
... 50 shrinks omitted ...
68126922926972637   -- 56 bits

【问题讨论】:

  • 显然罪魁祸首是第二个Gen.integral;将其替换为 Gen.integral_ 会将全部缩减的预算放在第一个 Gen.integral 上。

标签: haskell haskell-hedgehog


【解决方案1】:

你展示的输出对我来说非常有意义。

首先,为了确保我们在同一个页面上,Gen.print 显示的不是一系列假设失败的后续收缩,它只是收缩的第一级树。

因此,在您的示例中,它生成了68126922926972638,这是一个 7 字节的值。假设这失败了,它将尝试112,一个 1 字节的值。这是尽可能小的,因为它对应于您的第一个生成器的值0。如果这个测试也失败了,它会移动到收缩树的第二层,这是我们看不到的,但可以合理地假设它将专注于 1 字节值并尝试将它们收缩到 lo .

但是,如果112 的测试成功,它将移至列表中的第二个值4035711763,这是一个 4 字节值。请注意,4 个字节对应于您的第一个生成器中的3,它位于06 的中间,因为它正在对您的输入大小进行二进制搜索。如果测试再次成功,它将继续接近原始结果,即“强调其初始结果的附近”,这就是我们在您的输出中看到的。

【讨论】:

    猜你喜欢
    • 2015-10-24
    • 2014-03-06
    • 1970-01-01
    • 1970-01-01
    • 2019-06-18
    • 2012-07-21
    • 2013-04-24
    • 2022-07-27
    • 1970-01-01
    相关资源
    最近更新 更多