使用无限列表创建元素生成器

Create an elements generator with an infinite list

我正在玩 QuickCheck,偶然发现了一些奇怪的行为

sample $ elements [1..5]

按预期工作,但是

sample $ elements [1..]

在 ghci 中挂起,即使使用诸如 Int

的有限类型也是如此
sample $ elements [(1::Int)..]

为什么它不打印任意(双关语意:)大 Ints?

更新

我已经使用

测试了@amalloy 的解释
sample $ elements ([1 .. ] :: [Int8])

确实会终止。

elements 随机均匀选择元素,这意味着它平均将达到 length / 2 项进入列表。对于无穷大的值,这是不可能的,对于像 [1..] :: [Int] 这样的大型有限列表,这仍然达到了 10 亿个项目,通过链表一次一个。相当慢的操作!

似乎 elements 的文档很少。除了非空之外,参数还应该是 finite。查看源码:

-- | Generates one of the given values. The input list must be non-empty.
elements :: [a] -> Gen a
elements [] = error "QuickCheck.elements used with empty list"
elements xs = (xs !!) `fmap` choose (0, length xs - 1)

它尝试计算输入列表的长度,这将导致无限列表上的无限循环。