You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么Haskell QuickCheck自定义Arbitrary实例的shrink未被调用?

问题原因

你遇到的shrink未调用、无收缩操作的核心原因是前置条件过滤了所有收缩候选:

  • 你定义的属性前置条件为 length s > 5,即要求测试字符串长度至少为6
  • 触发失败的反例长度恰好为6,而你实现的shrink逻辑是每次删除一个字符,所有收缩生成的字符串长度都为5,完全不满足前置条件
  • QuickCheck在收缩流程中会自动丢弃所有不满足==>前置条件的候选,当没有任何有效收缩候选可用时,就会直接终止收缩流程,最终表现为numShrinks和numShrinkTries均为0

验证方法

你可以做任意一个修改验证该结论:

  1. 把前置条件调整为 length s >= 5,收缩后长度为5的字符串可以通过前置检查,就能触发正常的收缩流程,你添加的trace日志也会正常输出
  2. 把长度限制逻辑移到生成器内部,同时调整shrink逻辑保证收缩后的结果仍满足长度要求,避免无效收缩候选被过滤,示例如下:
-- 生成器保证输出长度>=6的字符串
simpleString = sized $ \n -> do
  len <- choose (6, max 6 n)
  replicateM len $ choose ('a','d')

-- shrink逻辑保证收缩后长度仍>=6
shrink (SimpleString ss) = 
  [SimpleString ss' | ss' <- removeOne ss, length ss' >= 6]

内容的提问来源于stack exchange,提问作者Ernesto Posse

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 18:27:04