对于给定的谓词pred : 'a list -> bool
和生成器gen : Gen<'a>
,请考虑以下满足条件的格式良好的列表生成器:
let wellFormedList pred gen =
Gen.ofList gen
|> Gen.filter pred
如FsCheck manual中所述,谓词对于随机列表的保留率应该很高。 不幸的是,这种假设在我看来并不成立。因此,我需要为满足谓词的列表定义自定义生成器。
如何定义自定义生成器,该生成器从空列表开始并使用新的随机元素扩展它,直到列表满足谓词为止?
我可能需要对生成器使用计算表达式gen { }
,但我看不到如何。
PS:我知道,与wellFormedList
的原始实现不同,此类自定义生成器的分布在满足谓词的所有列表上并不统一。
答案 0 :(得分:1)
如果我理解正确的话,我认为应该这样做:
let wellFormedList (predicate:'a list -> bool) (myGen:Gen<'a>) =
gen {
let! initialList = Gen.listOf myGen
let mutable myList = initialList
while not <| predicate myList do
let! newVal = myGen
myList <- (newVal :: myList)
return myList
}
或者如果您需要递归函数:
let wellFormedList (predicate:'a list -> bool) (myGen:Gen<'a>) =
gen {
let rec addIfNecessary listSoFar =
if predicate listSoFar
then gen { return listSoFar }
else gen {
let! newVal = myGen
return! addIfNecessary (newVal :: listSoFar)
}
let! initialList = Gen.listOf myGen
return! addIfNecessary initialList
}
我还没有检查能给您带来什么样的分布。当然,如果列表永远不会收敛于通过谓词的形式,那么您将面临无限循环(或堆栈溢出)的风险。